|
31 | 31 | import org.bouncycastle.asn1.DERUTF8String; |
32 | 32 | import org.bouncycastle.asn1.cms.Attribute; |
33 | 33 | import org.bouncycastle.asn1.cms.AttributeTable; |
| 34 | +import org.bouncycastle.asn1.cms.ContentInfo; |
| 35 | +import org.bouncycastle.asn1.cms.EnvelopedData; |
| 36 | +import org.bouncycastle.asn1.cms.KeyAgreeRecipientInfo; |
| 37 | +import org.bouncycastle.asn1.cms.RecipientInfo; |
| 38 | +import org.bouncycastle.asn1.cms.ecc.MQVuserKeyingMaterial; |
34 | 39 | import org.bouncycastle.asn1.kisa.KISAObjectIdentifiers; |
35 | 40 | import org.bouncycastle.asn1.nist.NISTObjectIdentifiers; |
36 | 41 | import org.bouncycastle.asn1.ntt.NTTObjectIdentifiers; |
@@ -1030,6 +1035,58 @@ public void testECMQVKeyAgreeMultiple() |
1030 | 1035 | confirmNumberRecipients(recipients, 2); |
1031 | 1036 | } |
1032 | 1037 |
|
| 1038 | + /* |
| 1039 | + * The 1-pass ECMQV ephemeral key pair is shared by the recipients of one KeyAgreeRecipientInfo, but |
| 1040 | + * a generator reused for a second message must not send the same ephemeral key again. |
| 1041 | + */ |
| 1042 | + public void testECMQVFreshEphemeralKeyPerMessage() |
| 1043 | + throws Exception |
| 1044 | + { |
| 1045 | + byte[] data = Hex.decode("504b492d4320434d5320456e76656c6f706564446174612053616d706c65"); |
| 1046 | + |
| 1047 | + JceKeyAgreeRecipientInfoGenerator recipientGenerator = new JceKeyAgreeRecipientInfoGenerator(CMSAlgorithm.ECMQV_SHA1KDF, |
| 1048 | + _origEcKP.getPrivate(), _origEcKP.getPublic(), CMSAlgorithm.AES128_WRAP).setProvider(BC); |
| 1049 | + |
| 1050 | + recipientGenerator.addRecipient(_reciEcCert); |
| 1051 | + recipientGenerator.addRecipient(_reciEcCert2); |
| 1052 | + |
| 1053 | + CMSEnvelopedDataGenerator edGen = new CMSEnvelopedDataGenerator(); |
| 1054 | + |
| 1055 | + edGen.addRecipientInfoGenerator(recipientGenerator); |
| 1056 | + |
| 1057 | + CMSEnvelopedData ed1 = edGen.generate( |
| 1058 | + new CMSProcessableByteArray(data), |
| 1059 | + new JceCMSContentEncryptorBuilder(CMSAlgorithm.AES128_CBC).setProvider(BC).build()); |
| 1060 | + CMSEnvelopedData ed2 = edGen.generate( |
| 1061 | + new CMSProcessableByteArray(data), |
| 1062 | + new JceCMSContentEncryptorBuilder(CMSAlgorithm.AES128_CBC).setProvider(BC).build()); |
| 1063 | + |
| 1064 | + byte[] ephemeral1 = getMQVEphemeralPublicKey(ed1); |
| 1065 | + byte[] ephemeral2 = getMQVEphemeralPublicKey(ed2); |
| 1066 | + |
| 1067 | + assertFalse("ephemeral key reused across messages", Arrays.equals(ephemeral1, ephemeral2)); |
| 1068 | + |
| 1069 | + confirmDataReceived(ed1.getRecipientInfos(), data, _reciEcCert, _reciEcKP.getPrivate(), BC); |
| 1070 | + confirmDataReceived(ed1.getRecipientInfos(), data, _reciEcCert2, _reciEcKP2.getPrivate(), BC); |
| 1071 | + confirmDataReceived(ed2.getRecipientInfos(), data, _reciEcCert, _reciEcKP.getPrivate(), BC); |
| 1072 | + confirmDataReceived(ed2.getRecipientInfos(), data, _reciEcCert2, _reciEcKP2.getPrivate(), BC); |
| 1073 | + } |
| 1074 | + |
| 1075 | + private static byte[] getMQVEphemeralPublicKey(CMSEnvelopedData ed) |
| 1076 | + throws IOException |
| 1077 | + { |
| 1078 | + EnvelopedData env = EnvelopedData.getInstance(ContentInfo.getInstance(ed.getEncoded()).getContent()); |
| 1079 | + assertEquals(1, env.getRecipientInfos().size()); |
| 1080 | + |
| 1081 | + KeyAgreeRecipientInfo kari = KeyAgreeRecipientInfo.getInstance( |
| 1082 | + RecipientInfo.getInstance(env.getRecipientInfos().getObjectAt(0)).getInfo()); |
| 1083 | + assertEquals(2, kari.getRecipientEncryptedKeys().size()); |
| 1084 | + |
| 1085 | + MQVuserKeyingMaterial ukm = MQVuserKeyingMaterial.getInstance(kari.getUserKeyingMaterial().getOctets()); |
| 1086 | + |
| 1087 | + return ukm.getEphemeralPublicKey().getPublicKeyData().getBytes(); |
| 1088 | + } |
| 1089 | + |
1033 | 1090 | private static void confirmDataReceived(RecipientInformationStore recipients, |
1034 | 1091 | byte[] expectedData, X509Certificate reciCert, PrivateKey reciPrivKey, String provider) |
1035 | 1092 | throws CMSException, NoSuchProviderException, CertificateEncodingException, IOException |
|
0 commit comments