Skip to content

Commit d360f5e

Browse files
committed
Support AES-GCM encryption
DEVSIX-8493
1 parent abf5c06 commit d360f5e

File tree

37 files changed

+1624
-51
lines changed

37 files changed

+1624
-51
lines changed

bouncy-castle-adapter/src/main/java/com/itextpdf/bouncycastle/BouncyCastleFactory.java

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -114,6 +114,7 @@ This file is part of the iText (R) project.
114114
import com.itextpdf.bouncycastle.cms.jcajce.JcaSimpleSignerInfoVerifierBuilderBC;
115115
import com.itextpdf.bouncycastle.cms.jcajce.JceKeyAgreeEnvelopedRecipientBC;
116116
import com.itextpdf.bouncycastle.cms.jcajce.JceKeyTransEnvelopedRecipientBC;
117+
import com.itextpdf.bouncycastle.crypto.modes.GCMBlockCipherBC;
117118
import com.itextpdf.bouncycastle.openssl.PEMParserBC;
118119
import com.itextpdf.bouncycastle.openssl.jcajce.JcaPEMKeyConverterBC;
119120
import com.itextpdf.bouncycastle.openssl.jcajce.JceOpenSSLPKCS8DecryptorProviderBuilderBC;
@@ -221,6 +222,7 @@ This file is part of the iText (R) project.
221222
import com.itextpdf.commons.bouncycastle.cms.jcajce.IJcaSimpleSignerInfoVerifierBuilder;
222223
import com.itextpdf.commons.bouncycastle.cms.jcajce.IJceKeyAgreeEnvelopedRecipient;
223224
import com.itextpdf.commons.bouncycastle.cms.jcajce.IJceKeyTransEnvelopedRecipient;
225+
import com.itextpdf.commons.bouncycastle.crypto.modes.IGCMBlockCipher;
224226
import com.itextpdf.commons.bouncycastle.openssl.IPEMParser;
225227
import com.itextpdf.commons.bouncycastle.openssl.jcajce.IJcaPEMKeyConverter;
226228
import com.itextpdf.commons.bouncycastle.openssl.jcajce.IJceOpenSSLPKCS8DecryptorProviderBuilder;
@@ -320,6 +322,8 @@ This file is part of the iText (R) project.
320322
import org.bouncycastle.crypto.digests.SHA256Digest;
321323
import org.bouncycastle.crypto.generators.HKDFBytesGenerator;
322324
import org.bouncycastle.crypto.params.HKDFParameters;
325+
import org.bouncycastle.crypto.engines.AESEngine;
326+
import org.bouncycastle.crypto.modes.GCMBlockCipher;
323327
import org.bouncycastle.jce.provider.BouncyCastleProvider;
324328
import org.bouncycastle.openssl.PEMParser;
325329
import org.bouncycastle.openssl.jcajce.JcaPEMKeyConverter;
@@ -1893,4 +1897,13 @@ public byte[] generateEncryptedKeyWithAES256NoPad(byte[] key, byte[] kek) throws
18931897
cipher.init(Cipher.WRAP_MODE, new SecretKeySpec(kek, "AESWrap"));
18941898
return cipher.wrap(new SecretKeySpec(key, "AESWrap"));
18951899
}
1900+
1901+
/**
1902+
* {@inheritDoc}
1903+
*/
1904+
@Override
1905+
public IGCMBlockCipher createGCMBlockCipher() {
1906+
GCMBlockCipher cipher = (GCMBlockCipher) GCMBlockCipher.newInstance(AESEngine.newInstance());
1907+
return new GCMBlockCipherBC(cipher);
1908+
}
18961909
}
Lines changed: 132 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,132 @@
1+
/*
2+
This file is part of the iText (R) project.
3+
Copyright (c) 1998-2024 Apryse Group NV
4+
Authors: Apryse Software.
5+
6+
This program is offered under a commercial and under the AGPL license.
7+
For commercial licensing, contact us at https://itextpdf.com/sales. For AGPL licensing, see below.
8+
9+
AGPL licensing:
10+
This program is free software: you can redistribute it and/or modify
11+
it under the terms of the GNU Affero General Public License as published by
12+
the Free Software Foundation, either version 3 of the License, or
13+
(at your option) any later version.
14+
15+
This program is distributed in the hope that it will be useful,
16+
but WITHOUT ANY WARRANTY; without even the implied warranty of
17+
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18+
GNU Affero General Public License for more details.
19+
20+
You should have received a copy of the GNU Affero General Public License
21+
along with this program. If not, see <https://www.gnu.org/licenses/>.
22+
*/
23+
package com.itextpdf.bouncycastle.crypto.modes;
24+
25+
import com.itextpdf.commons.bouncycastle.crypto.modes.IGCMBlockCipher;
26+
import org.bouncycastle.crypto.InvalidCipherTextException;
27+
import org.bouncycastle.crypto.modes.GCMBlockCipher;
28+
import org.bouncycastle.crypto.params.AEADParameters;
29+
import org.bouncycastle.crypto.params.KeyParameter;
30+
31+
import java.util.Objects;
32+
33+
/**
34+
* This class provides the functionality of a cryptographic cipher of aes-gcm for encryption and decryption via
35+
* wrapping the corresponding {@code GCMBlockCipher} class from bouncy-castle.
36+
*/
37+
public class GCMBlockCipherBC implements IGCMBlockCipher {
38+
private final GCMBlockCipher cipher;
39+
40+
/**
41+
* Creates new wrapper for {@link GCMBlockCipher} aes-gcm block cipher class.
42+
*
43+
* @param cipher bouncy-castle class to wrap
44+
*/
45+
public GCMBlockCipherBC(GCMBlockCipher cipher) {
46+
this.cipher = cipher;
47+
}
48+
49+
/**
50+
* Gets actual org.bouncycastle object being wrapped.
51+
*
52+
* @return wrapped {@link GCMBlockCipher}
53+
*/
54+
public GCMBlockCipher getCipher() {
55+
return cipher;
56+
}
57+
58+
/**
59+
* {@inheritDoc}
60+
*/
61+
@Override
62+
public void init(boolean forEncryption, byte[] key, int macSizeBits, byte[] iv) {
63+
cipher.init(forEncryption, new AEADParameters(new KeyParameter(key), macSizeBits, iv));
64+
}
65+
66+
/**
67+
* {@inheritDoc}
68+
*/
69+
@Override
70+
public int getUpdateOutputSize(int len) {
71+
return cipher.getUpdateOutputSize(len);
72+
}
73+
74+
/**
75+
* {@inheritDoc}
76+
*/
77+
@Override
78+
public void processBytes(byte[] input, int inputOffset, int len, byte[] output, int outOffset) {
79+
cipher.processBytes(input, inputOffset, len, output, outOffset);
80+
}
81+
82+
/**
83+
* {@inheritDoc}
84+
*/
85+
@Override
86+
public int getOutputSize(int len) {
87+
return cipher.getOutputSize(len);
88+
}
89+
90+
/**
91+
* {@inheritDoc}
92+
*/
93+
@Override
94+
public void doFinal(byte[] plainText, int i) {
95+
try {
96+
cipher.doFinal(plainText, i);
97+
} catch (InvalidCipherTextException e) {
98+
throw new IllegalArgumentException(e.getMessage(), e);
99+
}
100+
}
101+
102+
/**
103+
* {@inheritDoc}
104+
*/
105+
@Override
106+
public boolean equals(Object o) {
107+
if (this == o) {
108+
return true;
109+
}
110+
if (o == null || getClass() != o.getClass()) {
111+
return false;
112+
}
113+
GCMBlockCipherBC that = (GCMBlockCipherBC) o;
114+
return Objects.equals(cipher, that.cipher);
115+
}
116+
117+
/**
118+
* {@inheritDoc}
119+
*/
120+
@Override
121+
public int hashCode() {
122+
return Objects.hash(cipher);
123+
}
124+
125+
/**
126+
* {@inheritDoc}
127+
*/
128+
@Override
129+
public String toString() {
130+
return cipher.toString();
131+
}
132+
}

bouncy-castle-connector/src/main/java/com/itextpdf/bouncycastleconnector/BouncyCastleDefaultFactory.java

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -117,6 +117,7 @@ This file is part of the iText (R) project.
117117
import com.itextpdf.commons.bouncycastle.cms.jcajce.IJcaSimpleSignerInfoVerifierBuilder;
118118
import com.itextpdf.commons.bouncycastle.cms.jcajce.IJceKeyAgreeEnvelopedRecipient;
119119
import com.itextpdf.commons.bouncycastle.cms.jcajce.IJceKeyTransEnvelopedRecipient;
120+
import com.itextpdf.commons.bouncycastle.crypto.modes.IGCMBlockCipher;
120121
import com.itextpdf.commons.bouncycastle.openssl.IPEMParser;
121122
import com.itextpdf.commons.bouncycastle.openssl.jcajce.IJcaPEMKeyConverter;
122123
import com.itextpdf.commons.bouncycastle.openssl.jcajce.IJceOpenSSLPKCS8DecryptorProviderBuilder;
@@ -1007,4 +1008,9 @@ public byte[] generateHMACSHA256Token(byte[] key, byte[] data) {
10071008
public byte[] generateEncryptedKeyWithAES256NoPad(byte[] key, byte[] kek) {
10081009
throw new UnsupportedOperationException(BouncyCastleLogMessageConstant.BOUNCY_CASTLE_DEPENDENCY_MUST_PRESENT);
10091010
}
1011+
1012+
@Override
1013+
public IGCMBlockCipher createGCMBlockCipher() {
1014+
throw new UnsupportedOperationException(BouncyCastleLogMessageConstant.BOUNCY_CASTLE_DEPENDENCY_MUST_PRESENT);
1015+
}
10101016
}

bouncy-castle-fips-adapter/src/main/java/com/itextpdf/bouncycastlefips/BouncyCastleFipsFactory.java

Lines changed: 36 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -115,6 +115,7 @@ This file is part of the iText (R) project.
115115
import com.itextpdf.bouncycastlefips.cms.jcajce.JceKeyAgreeEnvelopedRecipientBCFips;
116116
import com.itextpdf.bouncycastlefips.cms.jcajce.JceKeyTransEnvelopedRecipientBCFips;
117117
import com.itextpdf.bouncycastlefips.crypto.fips.FipsUnapprovedOperationErrorBCFips;
118+
import com.itextpdf.bouncycastlefips.crypto.modes.GCMBlockCipherBCFips;
118119
import com.itextpdf.bouncycastlefips.openssl.PEMParserBCFips;
119120
import com.itextpdf.bouncycastlefips.openssl.jcajce.JcaPEMKeyConverterBCFips;
120121
import com.itextpdf.bouncycastlefips.openssl.jcajce.JceOpenSSLPKCS8DecryptorProviderBuilderBCFips;
@@ -222,6 +223,7 @@ This file is part of the iText (R) project.
222223
import com.itextpdf.commons.bouncycastle.cms.jcajce.IJcaSimpleSignerInfoVerifierBuilder;
223224
import com.itextpdf.commons.bouncycastle.cms.jcajce.IJceKeyAgreeEnvelopedRecipient;
224225
import com.itextpdf.commons.bouncycastle.cms.jcajce.IJceKeyTransEnvelopedRecipient;
226+
import com.itextpdf.commons.bouncycastle.crypto.modes.IGCMBlockCipher;
225227
import com.itextpdf.commons.bouncycastle.openssl.IPEMParser;
226228
import com.itextpdf.commons.bouncycastle.openssl.jcajce.IJcaPEMKeyConverter;
227229
import com.itextpdf.commons.bouncycastle.openssl.jcajce.IJceOpenSSLPKCS8DecryptorProviderBuilder;
@@ -245,6 +247,7 @@ This file is part of the iText (R) project.
245247
import java.io.Reader;
246248
import java.math.BigInteger;
247249
import java.security.GeneralSecurityException;
250+
import java.security.NoSuchProviderException;
248251
import java.security.InvalidKeyException;
249252
import java.security.NoSuchAlgorithmException;
250253
import java.security.PrivateKey;
@@ -259,6 +262,7 @@ This file is part of the iText (R) project.
259262
import java.util.List;
260263
import java.util.Set;
261264
import javax.crypto.Cipher;
265+
import javax.crypto.NoSuchPaddingException;
262266
import javax.crypto.Mac;
263267
import javax.crypto.spec.SecretKeySpec;
264268
import org.bouncycastle.asn1.ASN1BitString;
@@ -871,7 +875,7 @@ public IAlgorithmIdentifier createAlgorithmIdentifier(IASN1ObjectIdentifier algo
871875
*/
872876
@Override
873877
public IAlgorithmIdentifier createAlgorithmIdentifier(IASN1ObjectIdentifier algorithm,
874-
IASN1Encodable parameters) {
878+
IASN1Encodable parameters) {
875879
ASN1ObjectIdentifierBCFips algorithmBCFips = (ASN1ObjectIdentifierBCFips) algorithm;
876880
ASN1EncodableBCFips encodableBCFips = (ASN1EncodableBCFips) parameters;
877881
return new AlgorithmIdentifierBCFips(
@@ -976,8 +980,8 @@ public IJcaDigestCalculatorProviderBuilder createJcaDigestCalculatorProviderBuil
976980
*/
977981
@Override
978982
public ICertificateID createCertificateID(IDigestCalculator digestCalculator,
979-
IX509CertificateHolder certificateHolder,
980-
BigInteger bigInteger) throws OCSPExceptionBCFips {
983+
IX509CertificateHolder certificateHolder,
984+
BigInteger bigInteger) throws OCSPExceptionBCFips {
981985
return new CertificateIDBCFips(digestCalculator, certificateHolder, bigInteger);
982986
}
983987

@@ -1011,7 +1015,7 @@ public IJcaX509CertificateHolder createJcaX509CertificateHolder(X509Certificate
10111015
*/
10121016
@Override
10131017
public IExtension createExtension(IASN1ObjectIdentifier objectIdentifier,
1014-
boolean critical, IASN1OctetString octetString) {
1018+
boolean critical, IASN1OctetString octetString) {
10151019
return new ExtensionBCFips(new Extension(((ASN1ObjectIdentifierBCFips) objectIdentifier)
10161020
.getASN1ObjectIdentifier(), critical, ((ASN1OctetStringBCFips) octetString).getOctetString()));
10171021
}
@@ -1065,7 +1069,7 @@ public IOCSPReqBuilder createOCSPReqBuilder() {
10651069
*/
10661070
@Override
10671071
public ISigPolicyQualifierInfo createSigPolicyQualifierInfo(IASN1ObjectIdentifier objectIdentifier,
1068-
IDERIA5String string) {
1072+
IDERIA5String string) {
10691073
return new SigPolicyQualifierInfoBCFips(objectIdentifier, string);
10701074
}
10711075

@@ -1138,7 +1142,7 @@ public IOCSPResponse createOCSPResponse(IOCSPResponseStatus respStatus, IRespons
11381142
*/
11391143
@Override
11401144
public IResponseBytes createResponseBytes(IASN1ObjectIdentifier asn1ObjectIdentifier,
1141-
IDEROctetString derOctetString) {
1145+
IDEROctetString derOctetString) {
11421146
return new ResponseBytesBCFips(asn1ObjectIdentifier, derOctetString);
11431147
}
11441148

@@ -1274,7 +1278,7 @@ public IDistributionPointName createDistributionPointName() {
12741278
@Override
12751279
public IDistributionPointName createDistributionPointName(IGeneralNames generalNames) {
12761280
return new DistributionPointNameBCFips(
1277-
new DistributionPointName(((GeneralNamesBCFips)generalNames).getGeneralNames()));
1281+
new DistributionPointName(((GeneralNamesBCFips) generalNames).getGeneralNames()));
12781282
}
12791283

12801284
/**
@@ -1302,7 +1306,7 @@ public IGeneralName createGeneralName() {
13021306
*/
13031307
@Override
13041308
public IOtherHashAlgAndValue createOtherHashAlgAndValue(IAlgorithmIdentifier algorithmIdentifier,
1305-
IASN1OctetString octetString) {
1309+
IASN1OctetString octetString) {
13061310
return new OtherHashAlgAndValueBCFips(algorithmIdentifier, octetString);
13071311
}
13081312

@@ -1311,7 +1315,7 @@ public IOtherHashAlgAndValue createOtherHashAlgAndValue(IAlgorithmIdentifier alg
13111315
*/
13121316
@Override
13131317
public ISignaturePolicyId createSignaturePolicyId(IASN1ObjectIdentifier objectIdentifier,
1314-
IOtherHashAlgAndValue algAndValue) {
1318+
IOtherHashAlgAndValue algAndValue) {
13151319
return new SignaturePolicyIdBCFips(objectIdentifier, algAndValue);
13161320
}
13171321

@@ -1320,8 +1324,8 @@ public ISignaturePolicyId createSignaturePolicyId(IASN1ObjectIdentifier objectId
13201324
*/
13211325
@Override
13221326
public ISignaturePolicyId createSignaturePolicyId(IASN1ObjectIdentifier objectIdentifier,
1323-
IOtherHashAlgAndValue algAndValue,
1324-
ISigPolicyQualifierInfo... policyQualifiers) {
1327+
IOtherHashAlgAndValue algAndValue,
1328+
ISigPolicyQualifierInfo... policyQualifiers) {
13251329
SigPolicyQualifierInfo[] qualifierInfos = new SigPolicyQualifierInfo[policyQualifiers.length];
13261330
for (int i = 0; i < qualifierInfos.length; ++i) {
13271331
qualifierInfos[i] = ((SigPolicyQualifierInfoBCFips) policyQualifiers[i]).getQualifierInfo();
@@ -1342,7 +1346,7 @@ public ISignaturePolicyIdentifier createSignaturePolicyIdentifier(ISignaturePoli
13421346
*/
13431347
@Override
13441348
public IEnvelopedData createEnvelopedData(IOriginatorInfo originatorInfo, IASN1Set set,
1345-
IEncryptedContentInfo encryptedContentInfo, IASN1Set set1) {
1349+
IEncryptedContentInfo encryptedContentInfo, IASN1Set set1) {
13461350
return new EnvelopedDataBCFips(originatorInfo, set, encryptedContentInfo, set1);
13471351
}
13481352

@@ -1359,7 +1363,7 @@ public IRecipientInfo createRecipientInfo(IKeyTransRecipientInfo keyTransRecipie
13591363
*/
13601364
@Override
13611365
public IEncryptedContentInfo createEncryptedContentInfo(IASN1ObjectIdentifier data,
1362-
IAlgorithmIdentifier algorithmIdentifier, IASN1OctetString octetString) {
1366+
IAlgorithmIdentifier algorithmIdentifier, IASN1OctetString octetString) {
13631367
return new EncryptedContentInfoBCFips(data, algorithmIdentifier, octetString);
13641368
}
13651369

@@ -1400,7 +1404,7 @@ public IRecipientIdentifier createRecipientIdentifier(IIssuerAndSerialNumber iss
14001404
*/
14011405
@Override
14021406
public IKeyTransRecipientInfo createKeyTransRecipientInfo(IRecipientIdentifier recipientIdentifier,
1403-
IAlgorithmIdentifier algorithmIdentifier, IASN1OctetString octetString) {
1407+
IAlgorithmIdentifier algorithmIdentifier, IASN1OctetString octetString) {
14041408
return new KeyTransRecipientInfoBCFips(recipientIdentifier, algorithmIdentifier, octetString);
14051409
}
14061410

@@ -1525,7 +1529,7 @@ public IJcaCertStore createJcaCertStore(List<Certificate> certificates) throws C
15251529
*/
15261530
@Override
15271531
public ITimeStampResponseGenerator createTimeStampResponseGenerator(ITimeStampTokenGenerator tokenGenerator,
1528-
Set<String> algorithms) {
1532+
Set<String> algorithms) {
15291533
return new TimeStampResponseGeneratorBCFips(tokenGenerator, algorithms);
15301534
}
15311535

@@ -1559,7 +1563,7 @@ public IJcaSignerInfoGeneratorBuilder createJcaSignerInfoGeneratorBuilder(
15591563
*/
15601564
@Override
15611565
public ITimeStampTokenGenerator createTimeStampTokenGenerator(ISignerInfoGenerator siGen, IDigestCalculator dgCalc,
1562-
IASN1ObjectIdentifier policy) throws TSPExceptionBCFips {
1566+
IASN1ObjectIdentifier policy) throws TSPExceptionBCFips {
15631567
return new TimeStampTokenGeneratorBCFips(siGen, dgCalc, policy);
15641568
}
15651569

@@ -1625,7 +1629,7 @@ public IX509v2CRLBuilder createX509v2CRLBuilder(IX500Name x500Name, Date date) {
16251629
*/
16261630
@Override
16271631
public IJcaX509v3CertificateBuilder createJcaX509v3CertificateBuilder(X509Certificate signingCert,
1628-
BigInteger certSerialNumber, Date startDate, Date endDate, IX500Name subjectDnName, PublicKey publicKey) {
1632+
BigInteger certSerialNumber, Date startDate, Date endDate, IX500Name subjectDnName, PublicKey publicKey) {
16291633
return new JcaX509v3CertificateBuilderBCFips(signingCert, certSerialNumber, startDate, endDate, subjectDnName,
16301634
publicKey);
16311635
}
@@ -1847,7 +1851,7 @@ public boolean isInApprovedOnlyMode() {
18471851
*/
18481852
@Override
18491853
public byte[] createCipherBytes(X509Certificate x509certificate, byte[] abyte0,
1850-
IAlgorithmIdentifier algorithmIdentifier)
1854+
IAlgorithmIdentifier algorithmIdentifier)
18511855
throws GeneralSecurityException {
18521856
Cipher cipher;
18531857
try {
@@ -1898,4 +1902,18 @@ public byte[] generateEncryptedKeyWithAES256NoPad(byte[] key, byte[] kek) throws
18981902
cipher.init(Cipher.WRAP_MODE, new SecretKeySpec(kek, "AESWrap"));
18991903
return cipher.wrap(new SecretKeySpec(key, "AESWrap"));
19001904
}
1905+
1906+
/**
1907+
* {@inheritDoc}
1908+
*/
1909+
@Override
1910+
public IGCMBlockCipher createGCMBlockCipher() {
1911+
Cipher cipher = null;
1912+
try {
1913+
cipher = Cipher.getInstance("AES/GCM/NoPadding", getProviderName());
1914+
} catch (NoSuchAlgorithmException | NoSuchProviderException | NoSuchPaddingException e) {
1915+
// Ignore.
1916+
}
1917+
return new GCMBlockCipherBCFips(cipher);
1918+
}
19011919
}

0 commit comments

Comments
 (0)