private void verifyParserAlgorithm(String algorithmOid, MimeBodyPart msg) throws Exception { SMIMEEnvelopedGenerator gen = new SMIMEEnvelopedGenerator(); gen.addRecipientInfoGenerator(new JceKeyTransRecipientInfoGenerator(_reciCert).setProvider(BC)); // // generate a MimeBodyPart object which encapsulates the content // we want encrypted. // MimeBodyPart mp = gen.generate( msg, new JceCMSContentEncryptorBuilder(new ASN1ObjectIdentifier(algorithmOid)) .setProvider(BC) .build()); SMIMEEnvelopedParser m = new SMIMEEnvelopedParser(mp); RecipientId recId = getRecipientId(_reciCert); RecipientInformationStore recipients = m.getRecipientInfos(); RecipientInformation recipient = recipients.get(recId); MimeBodyPart res = SMIMEUtil.toMimeBodyPart( recipient.getContent( new JceKeyTransEnvelopedRecipient(_reciKP.getPrivate()).setProvider(BC))); verifyMessageBytes(msg, res); }
public void testAES256CCM() throws Exception { byte[] data = "Eric H. Echidna".getBytes(); ASN1ObjectIdentifier macAlg = CMSAlgorithm.AES256_CCM; AlgorithmParameters algParams = AlgorithmParameters.getInstance("CCM", BC); algParams.init(new CCMParameters(Hex.decode("000102030405060708090a0b"), 16).getEncoded()); CMSAuthenticatedDataGenerator adGen = new CMSAuthenticatedDataGenerator(); X509CertificateHolder origCert = new X509CertificateHolder(_origCert.getEncoded()); adGen.setOriginatorInfo(new OriginatorInfoGenerator(origCert).generate()); adGen.addRecipientInfoGenerator( new JceKeyTransRecipientInfoGenerator(_reciCert).setProvider(BC)); CMSAuthenticatedData ad = adGen.generate( new CMSProcessableByteArray(data), new JceCMSMacCalculatorBuilder(macAlg) .setAlgorithmParameters(algParams) .setProvider(BC) .build()); assertTrue(ad.getOriginatorInfo().getCertificates().getMatches(null).contains(origCert)); RecipientInformationStore recipients = ad.getRecipientInfos(); assertEquals(ad.getMacAlgOID(), macAlg.getId()); Collection c = recipients.getRecipients(); assertEquals(1, c.size()); Iterator it = c.iterator(); while (it.hasNext()) { RecipientInformation recipient = (RecipientInformation) it.next(); assertEquals(recipient.getKeyEncryptionAlgOID(), PKCSObjectIdentifiers.rsaEncryption.getId()); byte[] recData = recipient.getContent( new JceKeyTransAuthenticatedRecipient(_reciKP.getPrivate()).setProvider(BC)); assertTrue(Arrays.equals(data, recData)); assertEquals(16, ad.getMac().length); assertTrue(Arrays.equals(ad.getMac(), recipient.getMac())); } }
public void testTwoRecipients() throws Exception { MimeBodyPart _msg = SMIMETestUtil.makeMimeBodyPart("WallaWallaWashington"); SMIMEEnvelopedGenerator gen = new SMIMEEnvelopedGenerator(); gen.addRecipientInfoGenerator(new JceKeyTransRecipientInfoGenerator(_reciCert).setProvider(BC)); gen.addRecipientInfoGenerator( new JceKeyTransRecipientInfoGenerator(_reciCert2).setProvider(BC)); // // generate a MimeBodyPart object which encapsulates the content // we want encrypted. // MimeBodyPart mp = gen.generate( _msg, new JceCMSContentEncryptorBuilder(CMSAlgorithm.RC2_CBC, 40).setProvider(BC).build()); SMIMEEnvelopedParser m = new SMIMEEnvelopedParser(mp); RecipientId recId = getRecipientId(_reciCert2); RecipientInformationStore recipients = m.getRecipientInfos(); RecipientInformation recipient = recipients.get(recId); FileBackedMimeBodyPart res = SMIMEUtil.toMimeBodyPart( recipient.getContentStream( new JceKeyTransEnvelopedRecipient(_reciKP2.getPrivate()).setProvider(BC))); verifyMessageBytes(_msg, res); m = new SMIMEEnvelopedParser(mp); res.dispose(); recId = getRecipientId(_reciCert); recipients = m.getRecipientInfos(); recipient = recipients.get(recId); res = SMIMEUtil.toMimeBodyPart( recipient.getContentStream( new JceKeyTransEnvelopedRecipient(_reciKP.getPrivate()).setProvider(BC))); verifyMessageBytes(_msg, res); res.dispose(); }
public void testAES256() throws Exception { MimeMessage message = loadMessage("test256.message"); SMIMEEnveloped env = new SMIMEEnveloped(message); RecipientInformationStore store = env.getRecipientInfos(); RecipientInformation recipInfo = store.get(new JceKeyTransRecipientId(loadCert("cert.pem"))); assertNotNull(recipInfo); byte[] content = recipInfo.getContent(new JceKeyTransEnvelopedRecipient(loadKey("key.pem"))); assertTrue(org.bouncycastle.util.Arrays.areEqual(testMessage, content)); }
public void testSubKeyId() throws Exception { MimeBodyPart msg = SMIMETestUtil.makeMimeBodyPart("WallaWallaWashington"); SMIMEEnvelopedGenerator gen = new SMIMEEnvelopedGenerator(); // // create a subject key id - this has to be done the same way as // it is done in the certificate associated with the private key // MessageDigest dig = MessageDigest.getInstance("SHA1", BC); dig.update( SubjectPublicKeyInfo.getInstance(_reciCert.getPublicKey().getEncoded()) .getPublicKeyData() .getBytes()); gen.addRecipientInfoGenerator( new JceKeyTransRecipientInfoGenerator(dig.digest(), _reciCert.getPublicKey()) .setProvider(BC)); // // generate a MimeBodyPart object which encapsulates the content // we want encrypted. // MimeBodyPart mp = gen.generate( msg, new JceCMSContentEncryptorBuilder(CMSAlgorithm.DES_EDE3_CBC).setProvider(BC).build()); SMIMEEnveloped m = new SMIMEEnveloped(mp); dig.update( SubjectPublicKeyInfo.getInstance(_reciCert.getPublicKey().getEncoded()) .getPublicKeyData() .getBytes()); RecipientId recId = new KeyTransRecipientId(dig.digest()); RecipientInformationStore recipients = m.getRecipientInfos(); RecipientInformation recipient = recipients.get(recId); MimeBodyPart res = SMIMEUtil.toMimeBodyPart( recipient.getContent( new JceKeyTransEnvelopedRecipient(_reciKP.getPrivate()).setProvider(BC))); verifyMessageBytes(msg, res); }
/** * Gets the content from a recipient. * * @param recipientInfo * @param certificateKey * @param certificateKeyProvider * @return * @throws CMSException */ public static byte[] getContent( RecipientInformation recipientInfo, PrivateKey certificateKey, String certificateKeyProvider) throws CMSException { Recipient jceKeyTransRecipient = new JceKeyTransEnvelopedRecipient(certificateKey).setProvider(certificateKeyProvider); return recipientInfo.getContent(jceKeyTransRecipient); }
private void tryKekAlgorithm(SecretKey kek, ASN1ObjectIdentifier algOid, byte[] encodedParameters) throws NoSuchAlgorithmException, NoSuchProviderException, CMSException, OperatorCreationException, IOException { byte[] data = "Eric H. Echidna".getBytes(); CMSAuthenticatedDataGenerator adGen = new CMSAuthenticatedDataGenerator(); byte[] kekId = new byte[] {1, 2, 3, 4, 5}; adGen.addRecipientInfoGenerator(new JceKEKRecipientInfoGenerator(kekId, kek).setProvider(BC)); AlgorithmParameters algParams = AlgorithmParameters.getInstance(CMSAlgorithm.DES_EDE3_CBC.getId(), "BC"); algParams.init(encodedParameters); CMSAuthenticatedData ad = adGen.generate( new CMSProcessableByteArray(data), new JceCMSMacCalculatorBuilder(CMSAlgorithm.DES_EDE3_CBC) .setAlgorithmParameters(algParams) .setProvider(BC) .build()); RecipientInformationStore recipients = ad.getRecipientInfos(); Collection c = recipients.getRecipients(); Iterator it = c.iterator(); assertEquals(ad.getMacAlgOID(), CMSAuthenticatedDataGenerator.DES_EDE3_CBC); assertEquals( ad.getMacAlgorithm().getParameters(), ASN1Primitive.fromByteArray(encodedParameters)); if (it.hasNext()) { RecipientInformation recipient = (RecipientInformation) it.next(); assertEquals(recipient.getKeyEncryptionAlgOID(), algOid.getId()); byte[] recData = recipient.getContent(new JceKEKAuthenticatedRecipient(kek).setProvider(BC)); assertTrue(Arrays.equals(data, recData)); assertTrue(Arrays.equals(ad.getMac(), recipient.getMac())); } else { fail("no recipient found"); } }
private void checkData(byte[] data, SecretKey kek, CMSAuthenticatedData ad) throws CMSException { RecipientInformationStore recipients = ad.getRecipientInfos(); Collection c = recipients.getRecipients(); Iterator it = c.iterator(); if (it.hasNext()) { RecipientInformation recipient = (RecipientInformation) it.next(); byte[] recData = recipient.getContent(new JceKEKAuthenticatedRecipient(kek).setProvider(BC)); assertTrue(Arrays.equals(data, recData)); assertTrue(Arrays.equals(ad.getMac(), recipient.getMac())); assertTrue(Arrays.equals(ad.getContentDigest(), recipient.getContentDigest())); } else { fail("no recipient found"); } }
public void testOriginatorInfo() throws Exception { byte[] data = "Eric H. Echidna".getBytes(); ASN1ObjectIdentifier macAlg = CMSAlgorithm.DES_EDE3_CBC; CMSAuthenticatedDataGenerator adGen = new CMSAuthenticatedDataGenerator(); X509CertificateHolder origCert = new X509CertificateHolder(_origCert.getEncoded()); adGen.setOriginatorInfo(new OriginatorInfoGenerator(origCert).generate()); adGen.addRecipientInfoGenerator( new JceKeyTransRecipientInfoGenerator(_reciCert).setProvider(BC)); CMSAuthenticatedData ad = adGen.generate( new CMSProcessableByteArray(data), new JceCMSMacCalculatorBuilder(macAlg).setProvider(BC).build()); assertTrue(ad.getOriginatorInfo().getCertificates().getMatches(null).contains(origCert)); RecipientInformationStore recipients = ad.getRecipientInfos(); assertEquals(ad.getMacAlgOID(), macAlg.getId()); Collection c = recipients.getRecipients(); assertEquals(1, c.size()); Iterator it = c.iterator(); while (it.hasNext()) { RecipientInformation recipient = (RecipientInformation) it.next(); assertEquals(recipient.getKeyEncryptionAlgOID(), PKCSObjectIdentifiers.rsaEncryption.getId()); byte[] recData = recipient.getContent( new JceKeyTransAuthenticatedRecipient(_reciKP.getPrivate()).setProvider(BC)); assertTrue(Arrays.equals(data, recData)); assertTrue(Arrays.equals(ad.getMac(), recipient.getMac())); } }
public void testECKeyAgree() throws Exception { byte[] data = Hex.decode("504b492d4320434d5320456e76656c6f706564446174612053616d706c65"); CMSAuthenticatedDataGenerator adGen = new CMSAuthenticatedDataGenerator(); JceKeyAgreeRecipientInfoGenerator recipientGenerator = new JceKeyAgreeRecipientInfoGenerator( CMSAlgorithm.ECDH_SHA1KDF, _origEcKP.getPrivate(), _origEcKP.getPublic(), CMSAlgorithm.AES128_WRAP) .setProvider(BC); recipientGenerator.addRecipient(_reciEcCert); adGen.addRecipientInfoGenerator(recipientGenerator); CMSAuthenticatedData ad = adGen.generate( new CMSProcessableByteArray(data), new JceCMSMacCalculatorBuilder(CMSAlgorithm.DES_EDE3_CBC).setProvider(BC).build()); RecipientInformationStore recipients = ad.getRecipientInfos(); assertEquals(ad.getMacAlgOID(), CMSAuthenticatedDataGenerator.DES_EDE3_CBC); Collection c = recipients.getRecipients(); Iterator it = c.iterator(); if (it.hasNext()) { RecipientInformation recipient = (RecipientInformation) it.next(); byte[] recData = recipient.getContent( new JceKeyAgreeAuthenticatedRecipient(_reciEcKP.getPrivate()).setProvider(BC)); assertTrue(Arrays.equals(data, recData)); assertTrue(Arrays.equals(ad.getMac(), recipient.getMac())); } else { fail("no recipient found"); } }
/** * Decrypts an entity with the provided certificates' private key. * * @param encryptedEntity The entity that will be decrypted. * @param decryptingCertificate The certificates whose private keys will be used to decrypt the * message. * @return A MimeEntity containing the decrypted part. */ public MimeEntity decrypt( MimeEntity encryptedEntity, Collection<X509CertificateEx> decryptingCertificates) { if (decryptingCertificates == null || decryptingCertificates.size() == 0) { throw new IllegalArgumentException(); } MimeEntity retEntity = null; try { if (LOGGER.isDebugEnabled()) { byte[] encryptedContent = encryptedEntity.getContentAsBytes(); writePreDecrypt(encryptedContent); } SMIMEEnveloped m = new SMIMEEnveloped(encryptedEntity); X509CertificateEx decryptCert = decryptingCertificates.iterator().next(); RecipientId recId = generateRecipientSelector(decryptCert); RecipientInformationStore recipients = m.getRecipientInfos(); RecipientInformation recipient = recipients.get(recId); byte[] decryptedPayload = recipient.getContent(decryptCert.getPrivateKey(), CryptoExtensions.getJCEProviderName()); if (LOGGER.isDebugEnabled()) { writePostDecrypt(decryptedPayload); } ByteArrayInputStream inStream = new ByteArrayInputStream(decryptedPayload); retEntity = new MimeEntity(inStream); } catch (MessagingException e) { throw new MimeException(MimeError.InvalidMimeEntity, e); } catch (Exception e) { throw new MimeException(MimeError.Unexpected, e); } return retEntity; }
private void tryKekAlgorithmWithDigest(SecretKey kek, ASN1ObjectIdentifier algOid) throws NoSuchAlgorithmException, NoSuchProviderException, CMSException, OperatorCreationException { byte[] data = "Eric H. Echidna".getBytes(); CMSAuthenticatedDataGenerator adGen = new CMSAuthenticatedDataGenerator(); DigestCalculatorProvider calcProvider = new JcaDigestCalculatorProviderBuilder().setProvider(BC).build(); byte[] kekId = new byte[] {1, 2, 3, 4, 5}; adGen.addRecipientInfoGenerator(new JceKEKRecipientInfoGenerator(kekId, kek).setProvider(BC)); CMSAuthenticatedData ad = adGen.generate( new CMSProcessableByteArray(data), new JceCMSMacCalculatorBuilder(CMSAlgorithm.DES_EDE3_CBC).setProvider(BC).build(), calcProvider.get(new AlgorithmIdentifier(OIWObjectIdentifiers.idSHA1))); RecipientInformationStore recipients = ad.getRecipientInfos(); Collection c = recipients.getRecipients(); Iterator it = c.iterator(); assertEquals(ad.getMacAlgOID(), CMSAuthenticatedDataGenerator.DES_EDE3_CBC); if (it.hasNext()) { RecipientInformation recipient = (RecipientInformation) it.next(); assertEquals(recipient.getKeyEncryptionAlgOID(), algOid.getId()); byte[] recData = recipient.getContent(new JceKEKAuthenticatedRecipient(kek).setProvider(BC)); assertTrue(Arrays.equals(data, recData)); assertTrue(Arrays.equals(ad.getMac(), recipient.getMac())); assertTrue(Arrays.equals(ad.getContentDigest(), recipient.getContentDigest())); } else { fail("no recipient found"); } }
private void tryKeyTransWithDigest(ASN1ObjectIdentifier macAlg) throws Exception { byte[] data = "Eric H. Echidna".getBytes(); CMSAuthenticatedDataGenerator adGen = new CMSAuthenticatedDataGenerator(); DigestCalculatorProvider calcProvider = new JcaDigestCalculatorProviderBuilder().setProvider(BC).build(); adGen.addRecipientInfoGenerator( new JceKeyTransRecipientInfoGenerator(_reciCert).setProvider(BC)); CMSAuthenticatedData ad = adGen.generate( new CMSProcessableByteArray(data), new JceCMSMacCalculatorBuilder(macAlg).setProvider(BC).build(), calcProvider.get(new AlgorithmIdentifier(OIWObjectIdentifiers.idSHA1))); RecipientInformationStore recipients = ad.getRecipientInfos(); assertEquals(ad.getMacAlgOID(), macAlg.getId()); Collection c = recipients.getRecipients(); assertEquals(1, c.size()); Iterator it = c.iterator(); while (it.hasNext()) { RecipientInformation recipient = (RecipientInformation) it.next(); assertEquals(recipient.getKeyEncryptionAlgOID(), PKCSObjectIdentifiers.rsaEncryption.getId()); byte[] recData = recipient.getContent( new JceKeyTransAuthenticatedRecipient(_reciKP.getPrivate()).setProvider(BC)); assertTrue(Arrays.equals(data, recData)); assertTrue(Arrays.equals(ad.getMac(), recipient.getMac())); assertTrue(Arrays.equals(ad.getContentDigest(), recipient.getContentDigest())); } }
/** * Prepares everything to decrypt the document. * * <p>If {@link #decryptDocument(PDDocument, DecryptionMaterial)} is used, this method is called * from there. Only if decryption of single objects is needed this should be called instead. * * @param encDictionary encryption dictionary, can be retrieved via {@link * PDDocument#getEncryptionDictionary()} * @param documentIDArray document id which is returned via {@link COSDocument#getDocumentID()} * (not used by this handler) * @param decryptionMaterial Information used to decrypt the document. * @throws IOException If there is an error accessing data. * @throws CryptographyException If there is an error with decryption. */ public void prepareForDecryption( PDEncryptionDictionary encDictionary, COSArray documentIDArray, DecryptionMaterial decryptionMaterial) throws CryptographyException, IOException { if (encDictionary.getLength() != 0) { this.keyLength = encDictionary.getLength(); } if (!(decryptionMaterial instanceof PublicKeyDecryptionMaterial)) { throw new CryptographyException( "Provided decryption material is not compatible with the document"); } PublicKeyDecryptionMaterial material = (PublicKeyDecryptionMaterial) decryptionMaterial; try { boolean foundRecipient = false; // the decrypted content of the enveloped data that match // the certificate in the decryption material provided byte[] envelopedData = null; // the bytes of each recipient in the recipients array byte[][] recipientFieldsBytes = new byte[encDictionary.getRecipientsLength()][]; int recipientFieldsLength = 0; for (int i = 0; i < encDictionary.getRecipientsLength(); i++) { COSString recipientFieldString = encDictionary.getRecipientStringAt(i); byte[] recipientBytes = recipientFieldString.getBytes(); CMSEnvelopedData data = new CMSEnvelopedData(recipientBytes); Iterator recipCertificatesIt = data.getRecipientInfos().getRecipients().iterator(); while (recipCertificatesIt.hasNext()) { RecipientInformation ri = (RecipientInformation) recipCertificatesIt.next(); // Impl: if a matching certificate was previously found it is an error, // here we just don't care about it if (ri.getRID().match(material.getCertificate()) && !foundRecipient) { foundRecipient = true; envelopedData = ri.getContent(material.getPrivateKey(), "BC"); } } recipientFieldsBytes[i] = recipientBytes; recipientFieldsLength += recipientBytes.length; } if (!foundRecipient || envelopedData == null) { throw new CryptographyException("The certificate matches no recipient entry"); } if (envelopedData.length != 24) { throw new CryptographyException("The enveloped data does not contain 24 bytes"); } // now envelopedData contains: // - the 20 bytes seed // - the 4 bytes of permission for the current user byte[] accessBytes = new byte[4]; System.arraycopy(envelopedData, 20, accessBytes, 0, 4); currentAccessPermission = new AccessPermission(accessBytes); currentAccessPermission.setReadOnly(); // what we will put in the SHA1 = the seed + each byte contained in the recipients array byte[] sha1Input = new byte[recipientFieldsLength + 20]; // put the seed in the sha1 input System.arraycopy(envelopedData, 0, sha1Input, 0, 20); // put each bytes of the recipients array in the sha1 input int sha1InputOffset = 20; for (int i = 0; i < recipientFieldsBytes.length; i++) { System.arraycopy( recipientFieldsBytes[i], 0, sha1Input, sha1InputOffset, recipientFieldsBytes[i].length); sha1InputOffset += recipientFieldsBytes[i].length; } MessageDigest md = MessageDigest.getInstance("SHA-1"); byte[] mdResult = md.digest(sha1Input); // we have the encryption key ... encryptionKey = new byte[this.keyLength / 8]; System.arraycopy(mdResult, 0, encryptionKey, 0, this.keyLength / 8); } catch (CMSException e) { throw new CryptographyException(e); } catch (KeyStoreException e) { throw new CryptographyException(e); } catch (NoSuchProviderException e) { throw new CryptographyException(e); } catch (NoSuchAlgorithmException e) { throw new CryptographyException(e); } }