Skip to content

Commit 1102d45

Browse files
committed
Add auth enveloped recipients for KEK and KeyAgree
Currently it is possible to use CMSAuthEnvelopedDataParser only with KeyTrans. This adds support for KEK and KeyAgree. The AEADInputDecryptor is separated to CMSInputAEADDecryptor as it is the same for all recipient types. A new test is added to properly test CMSAuthEnvelopedDataParser usage.
1 parent 7324d9a commit 1102d45

File tree

7 files changed

+698
-63
lines changed

7 files changed

+698
-63
lines changed
Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
package org.bouncycastle.cms;
2+
3+
import org.bouncycastle.asn1.x509.AlgorithmIdentifier;
4+
import org.bouncycastle.cms.jcajce.JceKEKAuthEnvelopedRecipient;
5+
import org.bouncycastle.jcajce.io.CipherInputStream;
6+
import org.bouncycastle.operator.InputAEADDecryptor;
7+
8+
import javax.crypto.Cipher;
9+
import java.io.IOException;
10+
import java.io.InputStream;
11+
import java.io.OutputStream;
12+
13+
public class CMSInputAEADDecryptor
14+
implements InputAEADDecryptor
15+
{
16+
final AlgorithmIdentifier contentEncryptionAlgorithm;
17+
18+
final Cipher dataCipher;
19+
20+
private InputStream inputStream;
21+
22+
public CMSInputAEADDecryptor(AlgorithmIdentifier contentEncryptionAlgorithm, Cipher dataCipher)
23+
{
24+
this.contentEncryptionAlgorithm = contentEncryptionAlgorithm;
25+
this.dataCipher = dataCipher;
26+
}
27+
28+
public AlgorithmIdentifier getAlgorithmIdentifier()
29+
{
30+
return contentEncryptionAlgorithm;
31+
}
32+
33+
public InputStream getInputStream(InputStream dataIn)
34+
{
35+
inputStream = dataIn;
36+
return new CipherInputStream(dataIn, dataCipher);
37+
}
38+
39+
public OutputStream getAADStream()
40+
{
41+
return new AADStream(dataCipher);
42+
}
43+
44+
public byte[] getMAC()
45+
{
46+
if (inputStream instanceof InputStreamWithMAC)
47+
{
48+
return ((InputStreamWithMAC)inputStream).getMAC();
49+
}
50+
return null;
51+
}
52+
53+
private static class AADStream
54+
extends OutputStream
55+
{
56+
private Cipher cipher;
57+
private byte[] oneByte = new byte[1];
58+
59+
public AADStream(Cipher cipher)
60+
{
61+
this.cipher = cipher;
62+
}
63+
64+
public void write(byte[] buf, int off, int len)
65+
throws IOException
66+
{
67+
cipher.updateAAD(buf, off, len);
68+
}
69+
70+
public void write(int b)
71+
throws IOException
72+
{
73+
oneByte[0] = (byte)b;
74+
75+
cipher.updateAAD(oneByte);
76+
}
77+
}
78+
}
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
package org.bouncycastle.cms.jcajce;
2+
3+
import org.bouncycastle.asn1.x509.AlgorithmIdentifier;
4+
import org.bouncycastle.cms.CMSException;
5+
import org.bouncycastle.cms.CMSInputAEADDecryptor;
6+
import org.bouncycastle.cms.RecipientOperator;
7+
8+
import javax.crypto.Cipher;
9+
import javax.crypto.SecretKey;
10+
import java.security.Key;
11+
12+
public class JceKEKAuthEnvelopedRecipient
13+
extends JceKEKRecipient
14+
{
15+
public JceKEKAuthEnvelopedRecipient(SecretKey recipientKey)
16+
{
17+
super(recipientKey);
18+
}
19+
20+
public RecipientOperator getRecipientOperator(AlgorithmIdentifier keyEncryptionAlgorithm, final AlgorithmIdentifier contentEncryptionAlgorithm, byte[] encryptedContentEncryptionKey)
21+
throws CMSException
22+
{
23+
Key secretKey = extractSecretKey(keyEncryptionAlgorithm, contentEncryptionAlgorithm, encryptedContentEncryptionKey);
24+
25+
final Cipher dataCipher = contentHelper.createContentCipher(secretKey, contentEncryptionAlgorithm);
26+
27+
return new RecipientOperator(new CMSInputAEADDecryptor(contentEncryptionAlgorithm, dataCipher));
28+
}
29+
}
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
package org.bouncycastle.cms.jcajce;
2+
3+
import org.bouncycastle.asn1.ASN1OctetString;
4+
import org.bouncycastle.asn1.x509.AlgorithmIdentifier;
5+
import org.bouncycastle.asn1.x509.SubjectPublicKeyInfo;
6+
import org.bouncycastle.cms.CMSException;
7+
import org.bouncycastle.cms.CMSInputAEADDecryptor;
8+
import org.bouncycastle.cms.RecipientOperator;
9+
10+
import javax.crypto.Cipher;
11+
import java.security.Key;
12+
import java.security.PrivateKey;
13+
14+
public class JceKeyAgreeAuthEnvelopedRecipient
15+
extends JceKeyAgreeRecipient
16+
{
17+
public JceKeyAgreeAuthEnvelopedRecipient(PrivateKey recipientKey)
18+
{
19+
super(recipientKey);
20+
}
21+
22+
public RecipientOperator getRecipientOperator(AlgorithmIdentifier keyEncryptionAlgorithm, final AlgorithmIdentifier contentEncryptionAlgorithm, SubjectPublicKeyInfo senderPublicKey, ASN1OctetString userKeyingMaterial, byte[] encryptedContentKey)
23+
throws CMSException
24+
{
25+
Key secretKey = extractSecretKey(keyEncryptionAlgorithm, contentEncryptionAlgorithm, senderPublicKey, userKeyingMaterial, encryptedContentKey);
26+
27+
final Cipher dataCipher = contentHelper.createContentCipher(secretKey, contentEncryptionAlgorithm);
28+
29+
return new RecipientOperator(new CMSInputAEADDecryptor(contentEncryptionAlgorithm, dataCipher));
30+
}
31+
}
Lines changed: 2 additions & 61 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,14 @@
11
package org.bouncycastle.cms.jcajce;
22

3-
import java.io.IOException;
4-
import java.io.InputStream;
5-
import java.io.OutputStream;
63
import java.security.Key;
74
import java.security.PrivateKey;
85

96
import javax.crypto.Cipher;
107

118
import org.bouncycastle.asn1.x509.AlgorithmIdentifier;
129
import org.bouncycastle.cms.CMSException;
13-
import org.bouncycastle.cms.InputStreamWithMAC;
10+
import org.bouncycastle.cms.CMSInputAEADDecryptor;
1411
import org.bouncycastle.cms.RecipientOperator;
15-
import org.bouncycastle.jcajce.io.CipherInputStream;
16-
import org.bouncycastle.operator.InputAEADDecryptor;
1712

1813
public class JceKeyTransAuthEnvelopedRecipient
1914
extends JceKeyTransRecipient
@@ -30,60 +25,6 @@ public RecipientOperator getRecipientOperator(AlgorithmIdentifier keyEncryptionA
3025

3126
final Cipher dataCipher = contentHelper.createContentCipher(secretKey, contentEncryptionAlgorithm);
3227

33-
return new RecipientOperator(new InputAEADDecryptor()
34-
{
35-
private InputStream inputStream;
36-
37-
public AlgorithmIdentifier getAlgorithmIdentifier()
38-
{
39-
return contentEncryptionAlgorithm;
40-
}
41-
42-
public InputStream getInputStream(InputStream dataIn)
43-
{
44-
inputStream = dataIn;
45-
return new CipherInputStream(dataIn, dataCipher);
46-
}
47-
48-
public OutputStream getAADStream()
49-
{
50-
return new AADStream(dataCipher);
51-
}
52-
53-
public byte[] getMAC()
54-
{
55-
if (inputStream instanceof InputStreamWithMAC)
56-
{
57-
return ((InputStreamWithMAC)inputStream).getMAC();
58-
}
59-
return null;
60-
}
61-
});
62-
}
63-
64-
private static class AADStream
65-
extends OutputStream
66-
{
67-
private Cipher cipher;
68-
private byte[] oneByte = new byte[1];
69-
70-
public AADStream(Cipher cipher)
71-
{
72-
this.cipher = cipher;
73-
}
74-
75-
public void write(byte[] buf, int off, int len)
76-
throws IOException
77-
{
78-
cipher.updateAAD(buf, off, len);
79-
}
80-
81-
public void write(int b)
82-
throws IOException
83-
{
84-
oneByte[0] = (byte)b;
85-
86-
cipher.updateAAD(oneByte);
87-
}
28+
return new RecipientOperator(new CMSInputAEADDecryptor(contentEncryptionAlgorithm, dataCipher));
8829
}
8930
}

pkix/src/test/java/org/bouncycastle/cms/test/AllTests.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ public static Test suite()
2828
suite.addTest(NewAuthenticatedDataStreamTest.suite());
2929
suite.addTest(NewCompressedDataStreamTest.suite());
3030
suite.addTest(NewSignedDataStreamTest.suite());
31+
suite.addTest(NewAuthEnvelopedDataStreamTest.suite());
3132
suite.addTest(NewEnvelopedDataStreamTest.suite());
3233
suite.addTest(AuthEnvelopedDataTest.suite());
3334

0 commit comments

Comments
 (0)