SignerInformation( SignerInfo info, ASN1ObjectIdentifier contentType, CMSProcessable content, IntDigestCalculator digestCalculator, SignatureAlgorithmIdentifierFinder sigAlgFinder) { this.info = info; this.contentType = contentType; this.sigAlgFinder = sigAlgFinder; this.isCounterSignature = contentType == null; SignerIdentifier s = info.getSID(); if (s.isTagged()) { ASN1OctetString octs = ASN1OctetString.getInstance(s.getId()); sid = new SignerId(octs.getOctets()); } else { IssuerAndSerialNumber iAnds = IssuerAndSerialNumber.getInstance(s.getId()); sid = new SignerId(iAnds.getName(), iAnds.getSerialNumber().getValue()); } this.digestAlgorithm = info.getDigestAlgorithm(); this.signedAttributeSet = info.getAuthenticatedAttributes(); this.unsignedAttributeSet = info.getUnauthenticatedAttributes(); this.encryptionAlgorithm = info.getDigestEncryptionAlgorithm(); this.signature = info.getEncryptedDigest().getOctets(); this.content = content; this.digestCalculator = digestCalculator; }
/** Tests the extension Freshest CRL DP. */ @Test public void testCRLFreshestCRL() throws Exception { final String cdpURL = "http://www.ejbca.org/foo/bar.crl"; final String freshestCdpURL = "http://www.ejbca.org/foo/delta.crl"; X509CAInfo cainfo = (X509CAInfo) testx509ca.getCAInfo(); X509CRL x509crl; byte[] cFreshestDpDER; cainfo.setUseCrlDistributionPointOnCrl(true); cainfo.setDefaultCRLDistPoint(cdpURL); cainfo.setCADefinedFreshestCRL(freshestCdpURL); caSession.editCA(roleMgmgToken, cainfo); publishingCrlSessionRemote.forceCRL(roleMgmgToken, testx509ca.getCAId()); x509crl = CertTools.getCRLfromByteArray(crlStoreSession.getLastCRL(cainfo.getSubjectDN(), false)); cFreshestDpDER = x509crl.getExtensionValue(Extension.freshestCRL.getId()); assertNotNull("CRL has no Freshest Distribution Point", cFreshestDpDER); ASN1InputStream aIn = new ASN1InputStream(new ByteArrayInputStream(cFreshestDpDER)); ASN1OctetString octs = (ASN1OctetString) aIn.readObject(); aIn = new ASN1InputStream(new ByteArrayInputStream(octs.getOctets())); CRLDistPoint cdp = CRLDistPoint.getInstance((ASN1Sequence) aIn.readObject()); DistributionPoint[] distpoints = cdp.getDistributionPoints(); assertEquals("More CRL Freshest distributions points than expected", 1, distpoints.length); assertEquals( "Freshest CRL distribution point is different", freshestCdpURL, ((DERIA5String) ((GeneralNames) distpoints[0].getDistributionPoint().getName()) .getNames()[0].getName()) .getString()); }
public byte[] getIV() { if (iv != null) { return iv.getOctets(); } else { return null; } }
private static ASN1Primitive getObject(String oid, byte[] ext) throws AnnotatedException { try { ASN1InputStream aIn = new ASN1InputStream(ext); ASN1OctetString octs = (ASN1OctetString) aIn.readObject(); aIn = new ASN1InputStream(octs.getOctets()); return aIn.readObject(); } catch (Exception e) { throw new AnnotatedException("exception processing extension " + oid, e); } }
/** Return an Extension ASN1Primitive from a CRL */ protected static ASN1Primitive getExtensionValue(X509CRL crl, String oid) throws IOException { if (crl == null) { return null; } byte[] bytes = crl.getExtensionValue(oid); if (bytes == null) { return null; } ASN1InputStream aIn = new ASN1InputStream(new ByteArrayInputStream(bytes)); ASN1OctetString octs = (ASN1OctetString) aIn.readObject(); aIn = new ASN1InputStream(new ByteArrayInputStream(octs.getOctets())); return aIn.readObject(); } // getExtensionValue
private byte[] getSubjectKeyId(X509Certificate cert) throws IOException { byte[] extvalue = cert.getExtensionValue(X509Extensions.SubjectKeyIdentifier.getId()); if (extvalue == null) { return null; } ASN1OctetString str = ASN1OctetString.getInstance( new ASN1InputStream(new ByteArrayInputStream(extvalue)).readObject()); SubjectKeyIdentifier keyId = SubjectKeyIdentifier.getInstance( new ASN1InputStream(new ByteArrayInputStream(str.getOctets())).readObject()); return keyId.getKeyIdentifier(); }
private static boolean certHasPolicy(X509Certificate cert, String sOid) { try { if (m_logger.isDebugEnabled()) m_logger.debug("Read cert policies: " + cert.getSerialNumber().toString()); ByteArrayInputStream bIn = new ByteArrayInputStream(cert.getEncoded()); ASN1InputStream aIn = new ASN1InputStream(bIn); ASN1Sequence seq = (ASN1Sequence) aIn.readObject(); X509CertificateStructure obj = new X509CertificateStructure(seq); TBSCertificateStructure tbsCert = obj.getTBSCertificate(); if (tbsCert.getVersion() == 3) { X509Extensions ext = tbsCert.getExtensions(); if (ext != null) { Enumeration en = ext.oids(); while (en.hasMoreElements()) { DERObjectIdentifier oid = (DERObjectIdentifier) en.nextElement(); X509Extension extVal = ext.getExtension(oid); ASN1OctetString oct = extVal.getValue(); ASN1InputStream extIn = new ASN1InputStream(new ByteArrayInputStream(oct.getOctets())); // if (oid.equals(X509Extensions.CertificatePolicies)) { // bc 146 ja jdk 1.6 puhul - // X509Extension.certificatePolicies if (oid.equals(X509Extension.certificatePolicies)) { // bc 146 ja jdk 1.6 puhul - // X509Extension.certificatePolicies ASN1Sequence cp = (ASN1Sequence) extIn.readObject(); for (int i = 0; i != cp.size(); i++) { PolicyInformation pol = PolicyInformation.getInstance(cp.getObjectAt(i)); DERObjectIdentifier dOid = pol.getPolicyIdentifier(); String soid2 = dOid.getId(); if (m_logger.isDebugEnabled()) m_logger.debug("Policy: " + soid2); if (soid2.startsWith(sOid)) return true; } } } } } } catch (Exception ex) { m_logger.error("Error reading cert policies: " + ex); } return false; }
/** * @return a list of URLs in String format with present freshest CRL extensions or an empty List */ public static List<String> extractFreshestCrlDistributionPoints(final X509CRL crl) { final List<String> freshestCdpUrls = new ArrayList<String>(); final byte[] extensionValue = crl.getExtensionValue(Extension.freshestCRL.getId()); if (extensionValue != null) { final ASN1OctetString asn1OctetString = getAsn1ObjectFromBytes(extensionValue, ASN1OctetString.class); if (asn1OctetString != null) { final ASN1Sequence asn1Sequence = getAsn1ObjectFromBytes(asn1OctetString.getOctets(), ASN1Sequence.class); if (asn1Sequence != null) { final CRLDistPoint cdp = CRLDistPoint.getInstance(asn1Sequence); for (final DistributionPoint distributionPoint : cdp.getDistributionPoints()) { freshestCdpUrls.add( ((DERIA5String) ((GeneralNames) distributionPoint.getDistributionPoint().getName()) .getNames()[0].getName()) .getString()); } } } } return freshestCdpUrls; }
public static String toString(final ASN1OctetString value) { return new String(value.getOctets()); }
@Override protected void onDocumentSigned(byte[] byteArray) { try { InputStream inputStream = new ByteArrayInputStream(byteArray); PDDocument document = PDDocument.load(inputStream); List<PDSignature> signatures = document.getSignatureDictionaries(); assertEquals(1, signatures.size()); for (PDSignature pdSignature : signatures) { byte[] contents = pdSignature.getContents(byteArray); byte[] signedContent = pdSignature.getSignedContent(byteArray); logger.info("Byte range : " + Arrays.toString(pdSignature.getByteRange())); // IOUtils.write(contents, new FileOutputStream("sig.p7s")); ASN1InputStream asn1sInput = new ASN1InputStream(contents); ASN1Sequence asn1Seq = (ASN1Sequence) asn1sInput.readObject(); logger.info("SEQ : " + asn1Seq.toString()); ASN1ObjectIdentifier oid = ASN1ObjectIdentifier.getInstance(asn1Seq.getObjectAt(0)); assertEquals(PKCSObjectIdentifiers.signedData, oid); SignedData signedData = SignedData.getInstance(DERTaggedObject.getInstance(asn1Seq.getObjectAt(1)).getObject()); ASN1Set digestAlgorithmSet = signedData.getDigestAlgorithms(); ASN1ObjectIdentifier oidDigestAlgo = ASN1ObjectIdentifier.getInstance( ASN1Sequence.getInstance(digestAlgorithmSet.getObjectAt(0)).getObjectAt(0)); DigestAlgorithm digestAlgorithm = DigestAlgorithm.forOID(oidDigestAlgo.getId()); logger.info("DIGEST ALGO : " + digestAlgorithm); ContentInfo encapContentInfo = signedData.getEncapContentInfo(); ASN1ObjectIdentifier contentTypeOID = encapContentInfo.getContentType(); logger.info("ENCAPSULATED CONTENT INFO TYPE : " + contentTypeOID); assertEquals(PKCSObjectIdentifiers.data, contentTypeOID); ASN1Encodable content = encapContentInfo.getContent(); logger.info("ENCAPSULATED CONTENT INFO CONTENT : " + content); assertNull(content); List<X509Certificate> certificates = extractCertificates(signedData); ASN1Set signerInfosAsn1 = signedData.getSignerInfos(); logger.info("SIGNER INFO ASN1 : " + signerInfosAsn1.toString()); SignerInfo signedInfo = SignerInfo.getInstance(ASN1Sequence.getInstance(signerInfosAsn1.getObjectAt(0))); ASN1Set authenticatedAttributeSet = signedInfo.getAuthenticatedAttributes(); logger.info("AUTHENTICATED ATTR : " + authenticatedAttributeSet); List<ASN1ObjectIdentifier> attributeOids = new ArrayList<ASN1ObjectIdentifier>(); for (int i = 0; i < authenticatedAttributeSet.size(); i++) { Attribute attribute = Attribute.getInstance(authenticatedAttributeSet.getObjectAt(i)); attributeOids.add(attribute.getAttrType()); } logger.info("List of OID for Auth Attrb : " + attributeOids); Attribute attributeDigest = Attribute.getInstance(authenticatedAttributeSet.getObjectAt(1)); assertEquals(PKCSObjectIdentifiers.pkcs_9_at_messageDigest, attributeDigest.getAttrType()); ASN1OctetString asn1ObjString = ASN1OctetString.getInstance(attributeDigest.getAttrValues().getObjectAt(0)); String embeddedDigest = Base64.encode(asn1ObjString.getOctets()); logger.info("MESSAGE DIGEST : " + embeddedDigest); byte[] digestSignedContent = DSSUtils.digest(digestAlgorithm, signedContent); String computedDigestSignedContentEncodeBase64 = Base64.encode(digestSignedContent); logger.info( "COMPUTED DIGEST SIGNED CONTENT BASE64 : " + computedDigestSignedContentEncodeBase64); assertEquals(embeddedDigest, computedDigestSignedContentEncodeBase64); SignerIdentifier sid = signedInfo.getSID(); logger.info("SIGNER IDENTIFIER : " + sid.getId()); IssuerAndSerialNumber issuerAndSerialNumber = IssuerAndSerialNumber.getInstance(signedInfo.getSID()); ASN1Integer signerSerialNumber = issuerAndSerialNumber.getSerialNumber(); logger.info( "ISSUER AND SN : " + issuerAndSerialNumber.getName() + " " + signerSerialNumber); BigInteger serial = issuerAndSerialNumber.getSerialNumber().getValue(); X509Certificate signerCertificate = null; for (X509Certificate x509Certificate : certificates) { if (serial.equals(x509Certificate.getSerialNumber())) { signerCertificate = x509Certificate; } } assertNotNull(signerCertificate); String algorithm = signerCertificate.getPublicKey().getAlgorithm(); EncryptionAlgorithm encryptionAlgorithm = EncryptionAlgorithm.forName(algorithm); ASN1OctetString encryptedInfoOctedString = signedInfo.getEncryptedDigest(); String signatureValue = Hex.toHexString(encryptedInfoOctedString.getOctets()); logger.info("SIGNATURE VALUE : " + signatureValue); Cipher cipher = Cipher.getInstance(encryptionAlgorithm.getName()); cipher.init(Cipher.DECRYPT_MODE, signerCertificate); byte[] decrypted = cipher.doFinal(encryptedInfoOctedString.getOctets()); ASN1InputStream inputDecrypted = new ASN1InputStream(decrypted); ASN1Sequence seqDecrypt = (ASN1Sequence) inputDecrypted.readObject(); logger.info("DECRYPTED : " + seqDecrypt); DigestInfo digestInfo = new DigestInfo(seqDecrypt); assertEquals(oidDigestAlgo, digestInfo.getAlgorithmId().getAlgorithm()); String decryptedDigestEncodeBase64 = Base64.encode(digestInfo.getDigest()); logger.info("DECRYPTED BASE64 : " + decryptedDigestEncodeBase64); byte[] encoded = authenticatedAttributeSet.getEncoded(); byte[] digest = DSSUtils.digest(digestAlgorithm, encoded); String computedDigestFromSignatureEncodeBase64 = Base64.encode(digest); logger.info( "COMPUTED DIGEST FROM SIGNATURE BASE64 : " + computedDigestFromSignatureEncodeBase64); assertEquals(decryptedDigestEncodeBase64, computedDigestFromSignatureEncodeBase64); IOUtils.closeQuietly(inputDecrypted); IOUtils.closeQuietly(asn1sInput); } IOUtils.closeQuietly(inputStream); document.close(); } catch (Exception e) { logger.error(e.getMessage(), e); fail(e.getMessage()); } }
private boolean doVerify(SignerInformationVerifier verifier) throws CMSException { String digestName = CMSSignedHelper.INSTANCE.getDigestAlgName(this.getDigestAlgOID()); String encName = CMSSignedHelper.INSTANCE.getEncryptionAlgName(this.getEncryptionAlgOID()); String signatureName = digestName + "with" + encName; try { if (digestCalculator != null) { resultDigest = digestCalculator.getDigest(); } else { DigestCalculator calc = verifier.getDigestCalculator(this.getDigestAlgorithmID()); if (content != null) { OutputStream digOut = calc.getOutputStream(); content.write(digOut); digOut.close(); } else if (signedAttributeSet == null) { // TODO Get rid of this exception and just treat content==null as empty not missing? throw new CMSException("data not encapsulated in signature - use detached constructor."); } resultDigest = calc.getDigest(); } } catch (IOException e) { throw new CMSException("can't process mime object to create signature.", e); } catch (NoSuchAlgorithmException e) { throw new CMSException("can't find algorithm: " + e.getMessage(), e); } catch (OperatorCreationException e) { throw new CMSException("can't create digest calculator: " + e.getMessage(), e); } // RFC 3852 11.1 Check the content-type attribute is correct { DERObject validContentType = getSingleValuedSignedAttribute(CMSAttributes.contentType, "content-type"); if (validContentType == null) { if (!isCounterSignature && signedAttributeSet != null) { throw new CMSException( "The content-type attribute type MUST be present whenever signed attributes are present in signed-data"); } } else { if (isCounterSignature) { throw new CMSException( "[For counter signatures,] the signedAttributes field MUST NOT contain a content-type attribute"); } if (!(validContentType instanceof DERObjectIdentifier)) { throw new CMSException( "content-type attribute value not of ASN.1 type 'OBJECT IDENTIFIER'"); } DERObjectIdentifier signedContentType = (DERObjectIdentifier) validContentType; if (!signedContentType.equals(contentType)) { throw new CMSException("content-type attribute value does not match eContentType"); } } } // RFC 3852 11.2 Check the message-digest attribute is correct { DERObject validMessageDigest = getSingleValuedSignedAttribute(CMSAttributes.messageDigest, "message-digest"); if (validMessageDigest == null) { if (signedAttributeSet != null) { throw new CMSException( "the message-digest signed attribute type MUST be present when there are any signed attributes present"); } } else { if (!(validMessageDigest instanceof ASN1OctetString)) { throw new CMSException("message-digest attribute value not of ASN.1 type 'OCTET STRING'"); } ASN1OctetString signedMessageDigest = (ASN1OctetString) validMessageDigest; if (!Arrays.constantTimeAreEqual(resultDigest, signedMessageDigest.getOctets())) { throw new CMSSignerDigestMismatchException( "message-digest attribute value does not match calculated value"); } } } // RFC 3852 11.4 Validate countersignature attribute(s) { AttributeTable signedAttrTable = this.getSignedAttributes(); if (signedAttrTable != null && signedAttrTable.getAll(CMSAttributes.counterSignature).size() > 0) { throw new CMSException("A countersignature attribute MUST NOT be a signed attribute"); } AttributeTable unsignedAttrTable = this.getUnsignedAttributes(); if (unsignedAttrTable != null) { ASN1EncodableVector csAttrs = unsignedAttrTable.getAll(CMSAttributes.counterSignature); for (int i = 0; i < csAttrs.size(); ++i) { Attribute csAttr = (Attribute) csAttrs.get(i); if (csAttr.getAttrValues().size() < 1) { throw new CMSException( "A countersignature attribute MUST contain at least one AttributeValue"); } // Note: We don't recursively validate the countersignature value } } } try { ContentVerifier contentVerifier = verifier.getContentVerifier(sigAlgFinder.find(signatureName)); OutputStream sigOut = contentVerifier.getOutputStream(); if (signedAttributeSet == null) { if (digestCalculator != null) { if (contentVerifier instanceof RawContentVerifier) { RawContentVerifier rawVerifier = (RawContentVerifier) contentVerifier; if (encName.equals("RSA")) { DigestInfo digInfo = new DigestInfo(digestAlgorithm, resultDigest); return rawVerifier.verify(digInfo.getDEREncoded(), this.getSignature()); } return rawVerifier.verify(resultDigest, this.getSignature()); } throw new CMSException("verifier unable to process raw signature"); } else if (content != null) { // TODO Use raw signature of the hash value instead content.write(sigOut); } } else { sigOut.write(this.getEncodedSignedAttributes()); } sigOut.close(); return contentVerifier.verify(this.getSignature()); } catch (IOException e) { throw new CMSException("can't process mime object to create signature.", e); } catch (OperatorCreationException e) { throw new CMSException("can't create content verifier: " + e.getMessage(), e); } }
/** @deprecated */ private boolean doVerify(PublicKey key, Provider sigProvider) throws CMSException, NoSuchAlgorithmException { String digestName = CMSSignedHelper.INSTANCE.getDigestAlgName(this.getDigestAlgOID()); String encName = CMSSignedHelper.INSTANCE.getEncryptionAlgName(this.getEncryptionAlgOID()); String signatureName = digestName + "with" + encName; Signature sig = CMSSignedHelper.INSTANCE.getSignatureInstance(signatureName, sigProvider); MessageDigest digest = CMSSignedHelper.INSTANCE.getDigestInstance(digestName, sigProvider); // TODO [BJA-109] Note: PSSParameterSpec requires JDK1.4+ /* try { DERObjectIdentifier sigAlgOID = encryptionAlgorithm.getObjectId(); DEREncodable sigParams = this.encryptionAlgorithm.getParameters(); if (sigAlgOID.equals(PKCSObjectIdentifiers.id_RSASSA_PSS)) { // RFC 4056 // When the id-RSASSA-PSS algorithm identifier is used for a signature, // the AlgorithmIdentifier parameters field MUST contain RSASSA-PSS-params. if (sigParams == null) { throw new CMSException( "RSASSA-PSS signature must specify algorithm parameters"); } AlgorithmParameters params = AlgorithmParameters.getInstance( sigAlgOID.getId(), sig.getProvider().getName()); params.init(sigParams.getDERObject().getEncoded(), "ASN.1"); PSSParameterSpec spec = (PSSParameterSpec)params.getParameterSpec(PSSParameterSpec.class); sig.setParameter(spec); } else { // TODO Are there other signature algorithms that provide parameters? if (sigParams != null) { throw new CMSException("unrecognised signature parameters provided"); } } } catch (IOException e) { throw new CMSException("error encoding signature parameters.", e); } catch (InvalidAlgorithmParameterException e) { throw new CMSException("error setting signature parameters.", e); } catch (InvalidParameterSpecException e) { throw new CMSException("error processing signature parameters.", e); } */ try { if (digestCalculator != null) { resultDigest = digestCalculator.getDigest(); } else { if (content != null) { content.write(new DigOutputStream(digest)); } else if (signedAttributeSet == null) { // TODO Get rid of this exception and just treat content==null as empty not missing? throw new CMSException("data not encapsulated in signature - use detached constructor."); } resultDigest = digest.digest(); } } catch (IOException e) { throw new CMSException("can't process mime object to create signature.", e); } // RFC 3852 11.1 Check the content-type attribute is correct { DERObject validContentType = getSingleValuedSignedAttribute(CMSAttributes.contentType, "content-type"); if (validContentType == null) { if (!isCounterSignature && signedAttributeSet != null) { throw new CMSException( "The content-type attribute type MUST be present whenever signed attributes are present in signed-data"); } } else { if (isCounterSignature) { throw new CMSException( "[For counter signatures,] the signedAttributes field MUST NOT contain a content-type attribute"); } if (!(validContentType instanceof DERObjectIdentifier)) { throw new CMSException( "content-type attribute value not of ASN.1 type 'OBJECT IDENTIFIER'"); } DERObjectIdentifier signedContentType = (DERObjectIdentifier) validContentType; if (!signedContentType.equals(contentType)) { throw new CMSException("content-type attribute value does not match eContentType"); } } } // RFC 3852 11.2 Check the message-digest attribute is correct { DERObject validMessageDigest = getSingleValuedSignedAttribute(CMSAttributes.messageDigest, "message-digest"); if (validMessageDigest == null) { if (signedAttributeSet != null) { throw new CMSException( "the message-digest signed attribute type MUST be present when there are any signed attributes present"); } } else { if (!(validMessageDigest instanceof ASN1OctetString)) { throw new CMSException("message-digest attribute value not of ASN.1 type 'OCTET STRING'"); } ASN1OctetString signedMessageDigest = (ASN1OctetString) validMessageDigest; if (!Arrays.constantTimeAreEqual(resultDigest, signedMessageDigest.getOctets())) { throw new CMSSignerDigestMismatchException( "message-digest attribute value does not match calculated value"); } } } // RFC 3852 11.4 Validate countersignature attribute(s) { AttributeTable signedAttrTable = this.getSignedAttributes(); if (signedAttrTable != null && signedAttrTable.getAll(CMSAttributes.counterSignature).size() > 0) { throw new CMSException("A countersignature attribute MUST NOT be a signed attribute"); } AttributeTable unsignedAttrTable = this.getUnsignedAttributes(); if (unsignedAttrTable != null) { ASN1EncodableVector csAttrs = unsignedAttrTable.getAll(CMSAttributes.counterSignature); for (int i = 0; i < csAttrs.size(); ++i) { Attribute csAttr = (Attribute) csAttrs.get(i); if (csAttr.getAttrValues().size() < 1) { throw new CMSException( "A countersignature attribute MUST contain at least one AttributeValue"); } // Note: We don't recursively validate the countersignature value } } } try { sig.initVerify(key); if (signedAttributeSet == null) { if (digestCalculator != null) { // need to decrypt signature and check message bytes return verifyDigest(resultDigest, key, this.getSignature(), sigProvider); } else if (content != null) { // TODO Use raw signature of the hash value instead content.write(new SigOutputStream(sig)); } } else { sig.update(this.getEncodedSignedAttributes()); } return sig.verify(this.getSignature()); } catch (InvalidKeyException e) { throw new CMSException("key not appropriate to signature in message.", e); } catch (IOException e) { throw new CMSException("can't process mime object to create signature.", e); } catch (SignatureException e) { throw new CMSException("invalid signature format in message: " + e.getMessage(), e); } }