Skip to content

Commit f498371

Browse files
committed
Merge branch '1794-auth-enveloped-recipients-kek-keyagree' into 'main'
Add auth enveloped recipients for KEK and KeyAgree See merge request root/bc-java!53
2 parents 33cbad1 + 3b7c94f commit f498371

File tree

8 files changed

+700
-64
lines changed

8 files changed

+700
-64
lines changed
Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
package org.bouncycastle.cms.jcajce;
2+
3+
import java.io.InputStream;
4+
import java.io.OutputStream;
5+
6+
import javax.crypto.Cipher;
7+
8+
import org.bouncycastle.asn1.x509.AlgorithmIdentifier;
9+
import org.bouncycastle.cms.InputStreamWithMAC;
10+
import org.bouncycastle.jcajce.io.CipherInputStream;
11+
import org.bouncycastle.operator.InputAEADDecryptor;
12+
13+
class CMSInputAEADDecryptor
14+
implements InputAEADDecryptor
15+
{
16+
private final AlgorithmIdentifier contentEncryptionAlgorithm;
17+
18+
private final Cipher dataCipher;
19+
20+
private InputStream inputStream;
21+
22+
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 JceAADStream(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+
}

pkix/src/main/java/org/bouncycastle/cms/jcajce/JceAADStream.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
class JceAADStream
99
extends OutputStream
1010
{
11-
private static final byte[] SINGLE_BYTE = new byte[1];
11+
private final byte[] SINGLE_BYTE = new byte[1];
1212
private Cipher cipher;
1313

1414
JceAADStream(Cipher cipher)
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
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.RecipientOperator;
6+
7+
import javax.crypto.Cipher;
8+
import javax.crypto.SecretKey;
9+
10+
import java.security.Key;
11+
12+
/**
13+
* A recipient for CMS authenticated enveloped data encrypted with a KEK (Key Encryption Key).
14+
* Handles key extraction and decryption of the content.
15+
*/
16+
public class JceKEKAuthEnvelopedRecipient
17+
extends JceKEKRecipient
18+
{
19+
public JceKEKAuthEnvelopedRecipient(SecretKey recipientKey)
20+
{
21+
super(recipientKey);
22+
}
23+
24+
public RecipientOperator getRecipientOperator(AlgorithmIdentifier keyEncryptionAlgorithm, final AlgorithmIdentifier contentEncryptionAlgorithm, byte[] encryptedContentEncryptionKey)
25+
throws CMSException
26+
{
27+
Key secretKey = extractSecretKey(keyEncryptionAlgorithm, contentEncryptionAlgorithm, encryptedContentEncryptionKey);
28+
29+
final Cipher dataCipher = contentHelper.createContentCipher(secretKey, contentEncryptionAlgorithm);
30+
31+
return new RecipientOperator(new CMSInputAEADDecryptor(contentEncryptionAlgorithm, dataCipher));
32+
}
33+
}
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
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.RecipientOperator;
8+
9+
import javax.crypto.Cipher;
10+
11+
import java.security.Key;
12+
import java.security.PrivateKey;
13+
14+
/**
15+
* A recipient class for CMS authenticated enveloped data using key agreement (Key Agreement Recipient).
16+
* Handles private key-based key extraction and content decryption.
17+
*/
18+
public class JceKeyAgreeAuthEnvelopedRecipient
19+
extends JceKeyAgreeRecipient
20+
{
21+
public JceKeyAgreeAuthEnvelopedRecipient(PrivateKey recipientKey)
22+
{
23+
super(recipientKey);
24+
}
25+
26+
public RecipientOperator getRecipientOperator(AlgorithmIdentifier keyEncryptionAlgorithm, final AlgorithmIdentifier contentEncryptionAlgorithm, SubjectPublicKeyInfo senderPublicKey, ASN1OctetString userKeyingMaterial, byte[] encryptedContentKey)
27+
throws CMSException
28+
{
29+
Key secretKey = extractSecretKey(keyEncryptionAlgorithm, contentEncryptionAlgorithm, senderPublicKey, userKeyingMaterial, encryptedContentKey);
30+
31+
final Cipher dataCipher = contentHelper.createContentCipher(secretKey, contentEncryptionAlgorithm);
32+
33+
return new RecipientOperator(new CMSInputAEADDecryptor(contentEncryptionAlgorithm, dataCipher));
34+
}
35+
}
Lines changed: 1 addition & 61 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,13 @@
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;
1410
import org.bouncycastle.cms.RecipientOperator;
15-
import org.bouncycastle.jcajce.io.CipherInputStream;
16-
import org.bouncycastle.operator.InputAEADDecryptor;
1711

1812
public class JceKeyTransAuthEnvelopedRecipient
1913
extends JceKeyTransRecipient
@@ -30,60 +24,6 @@ public RecipientOperator getRecipientOperator(AlgorithmIdentifier keyEncryptionA
3024

3125
final Cipher dataCipher = contentHelper.createContentCipher(secretKey, contentEncryptionAlgorithm);
3226

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-
}
27+
return new RecipientOperator(new CMSInputAEADDecryptor(contentEncryptionAlgorithm, dataCipher));
8828
}
8929
}

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)