Skip to content

Commit 4c6811e

Browse files
committed
Improve OAEP parameters matching
- add SHA-224 support and SHA-224, SHA-512 test coverage
1 parent 0fb2ec1 commit 4c6811e

File tree

4 files changed

+127
-54
lines changed

4 files changed

+127
-54
lines changed

core/src/main/java/org/bouncycastle/asn1/pkcs/RSAESOAEPparams.java

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -100,7 +100,17 @@ public AlgorithmIdentifier getPSourceAlgorithm()
100100
{
101101
return pSourceAlgorithm;
102102
}
103-
103+
104+
public RSAESOAEPparams withDefaultPSource()
105+
{
106+
if (DEFAULT_P_SOURCE_ALGORITHM == pSourceAlgorithm)
107+
{
108+
return this;
109+
}
110+
111+
return new RSAESOAEPparams(hashAlgorithm, maskGenAlgorithm, DEFAULT_P_SOURCE_ALGORITHM);
112+
}
113+
104114
/**
105115
* <pre>
106116
* RSAES-OAEP-params ::= SEQUENCE {
@@ -145,7 +155,7 @@ public ASN1Primitive toASN1Primitive()
145155
{
146156
v.add(new DERTaggedObject(true, 2, pSourceAlgorithm));
147157
}
148-
158+
149159
return new DERSequence(v);
150160
}
151161
}

pkix/src/main/java/org/bouncycastle/operator/jcajce/OperatorHelper.java

Lines changed: 70 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -23,13 +23,11 @@
2323
import javax.crypto.Cipher;
2424
import javax.crypto.KeyAgreement;
2525

26-
import org.bouncycastle.asn1.ASN1Encodable;
26+
import org.bouncycastle.asn1.ASN1Encoding;
2727
import org.bouncycastle.asn1.ASN1Integer;
2828
import org.bouncycastle.asn1.ASN1ObjectIdentifier;
29-
import org.bouncycastle.asn1.ASN1Primitive;
3029
import org.bouncycastle.asn1.ASN1Sequence;
3130
import org.bouncycastle.asn1.DERNull;
32-
import org.bouncycastle.asn1.DERSequence;
3331
import org.bouncycastle.asn1.cryptopro.CryptoProObjectIdentifiers;
3432
import org.bouncycastle.asn1.kisa.KISAObjectIdentifiers;
3533
import org.bouncycastle.asn1.nist.NISTObjectIdentifiers;
@@ -48,6 +46,7 @@
4846
import org.bouncycastle.jcajce.util.MessageDigestUtils;
4947
import org.bouncycastle.operator.DefaultSignatureNameFinder;
5048
import org.bouncycastle.operator.OperatorCreationException;
49+
import org.bouncycastle.util.Arrays;
5150
import org.bouncycastle.util.Integers;
5251

5352
class OperatorHelper
@@ -57,13 +56,11 @@ class OperatorHelper
5756
private static final Map symmetricWrapperAlgNames = new HashMap();
5857
private static final Map symmetricKeyAlgNames = new HashMap();
5958
private static final Map symmetricWrapperKeySizes = new HashMap();
59+
// ASN1ObjectIdentifier -> OAEPParamsValue
60+
private static final Map oaepParamsMap = new HashMap();
6061

6162
private static DefaultSignatureNameFinder sigFinder = new DefaultSignatureNameFinder();
6263

63-
private static final RSAESOAEPparams oaepParams_sha256 = calculateDefForDigest(NISTObjectIdentifiers.id_sha256);
64-
private static final RSAESOAEPparams oaepParams_sha384 = calculateDefForDigest(NISTObjectIdentifiers.id_sha384);
65-
private static final RSAESOAEPparams oaepParams_sha512 = calculateDefForDigest(NISTObjectIdentifiers.id_sha512);
66-
6764
static
6865
{
6966
oids.put(OIWObjectIdentifiers.idSHA1, "SHA1");
@@ -108,17 +105,12 @@ class OperatorHelper
108105
symmetricKeyAlgNames.put(NISTObjectIdentifiers.id_aes256_CBC, "AES");
109106
symmetricKeyAlgNames.put(PKCSObjectIdentifiers.des_EDE3_CBC, "DESede");
110107
symmetricKeyAlgNames.put(PKCSObjectIdentifiers.RC2_CBC, "RC2");
111-
}
112108

113-
private static RSAESOAEPparams calculateDefForDigest(ASN1ObjectIdentifier digest)
114-
{
115-
AlgorithmIdentifier hashAlgorithm = new AlgorithmIdentifier(
116-
digest,
117-
DERNull.INSTANCE);
118-
AlgorithmIdentifier maskGenAlgorithm = new AlgorithmIdentifier(
119-
PKCSObjectIdentifiers.id_mgf1,
120-
new AlgorithmIdentifier(digest, DERNull.INSTANCE));
121-
return new RSAESOAEPparams(hashAlgorithm, maskGenAlgorithm, RSAESOAEPparams.DEFAULT_P_SOURCE_ALGORITHM);
109+
OAEPParamsValue.add(oaepParamsMap, "RSA/ECB/OAEPWithSHA-1AndMGF1Padding", OIWObjectIdentifiers.idSHA1);
110+
OAEPParamsValue.add(oaepParamsMap, "RSA/ECB/OAEPWithSHA-224AndMGF1Padding", NISTObjectIdentifiers.id_sha224);
111+
OAEPParamsValue.add(oaepParamsMap, "RSA/ECB/OAEPWithSHA-256AndMGF1Padding", NISTObjectIdentifiers.id_sha256);
112+
OAEPParamsValue.add(oaepParamsMap, "RSA/ECB/OAEPWithSHA-384AndMGF1Padding", NISTObjectIdentifiers.id_sha384);
113+
OAEPParamsValue.add(oaepParamsMap, "RSA/ECB/OAEPWithSHA-512AndMGF1Padding", NISTObjectIdentifiers.id_sha512);
122114
}
123115

124116
private JcaJceHelper helper;
@@ -232,36 +224,25 @@ Cipher createAsymmetricWrapper(AlgorithmIdentifier algorithmID, Map extraAlgName
232224
{
233225
if (cipherName.indexOf("OAEPPadding") > 0)
234226
{
235-
ASN1Encodable algParams = algorithmID.getParameters();
236-
if (algParams != null)
227+
try
237228
{
238-
ASN1Primitive primitive = algParams.toASN1Primitive();
239-
if ((primitive instanceof ASN1Sequence))
229+
RSAESOAEPparams oaepParams = RSAESOAEPparams.getInstance(algorithmID.getParameters());
230+
if (oaepParams != null)
240231
{
241-
ASN1Sequence oaepParams = (ASN1Sequence)primitive;
242-
if (oaepParams.size() == 0)
243-
{
244-
cipherName = "RSA/ECB/OAEPWithSHA-1AndMGF1Padding";
245-
}
246-
else if (oaepParams.size() >= 2)
232+
ASN1ObjectIdentifier digestOID = oaepParams.getHashAlgorithm().getAlgorithm();
233+
OAEPParamsValue oaepParamsValue = (OAEPParamsValue)oaepParamsMap.get(digestOID);
234+
235+
// Note that the original pSourceAlgorithm is ignored for this comparison
236+
if (oaepParamsValue != null && oaepParamsValue.matches(oaepParams.withDefaultPSource()))
247237
{
248-
// we only check the first 2 as pSource may be different
249-
oaepParams = new DERSequence(new ASN1Encodable[]{ oaepParams.getObjectAt(0), oaepParams.getObjectAt(1) });
250-
if (oaepParams_sha256.equals(oaepParams))
251-
{
252-
cipherName = "RSA/ECB/OAEPWithSHA-256AndMGF1Padding";
253-
}
254-
else if (oaepParams_sha512.equals(oaepParams))
255-
{
256-
cipherName = "RSA/ECB/OAEPWithSHA-512AndMGF1Padding";
257-
}
258-
else if (oaepParams_sha384.equals(oaepParams))
259-
{
260-
cipherName = "RSA/ECB/OAEPWithSHA-384AndMGF1Padding";
261-
}
238+
cipherName = oaepParamsValue.getCipherName();
262239
}
263240
}
264241
}
242+
catch (Exception e)
243+
{
244+
// Ignore
245+
}
265246
}
266247

267248
try
@@ -637,4 +618,52 @@ private boolean notDefaultPSSParams(ASN1Sequence seq)
637618

638619
return pssParams.getSaltLength().intValue() != digest.getDigestLength();
639620
}
621+
622+
private static class OAEPParamsValue
623+
{
624+
static void add(Map oaepParamsMap, String cipherName, ASN1ObjectIdentifier digestOID)
625+
{
626+
try
627+
{
628+
RSAESOAEPparams oaepParams = createOAEPParams(digestOID);
629+
byte[] derEncoding = getDEREncoding(oaepParams);
630+
oaepParamsMap.put(digestOID, new OAEPParamsValue(cipherName, derEncoding));
631+
}
632+
catch (Exception e)
633+
{
634+
throw new RuntimeException(e);
635+
}
636+
}
637+
638+
private String cipherName;
639+
private byte[] derEncoding;
640+
641+
private OAEPParamsValue(String cipherName, byte[] derEncoding)
642+
{
643+
this.cipherName = cipherName;
644+
this.derEncoding = derEncoding;
645+
}
646+
647+
String getCipherName()
648+
{
649+
return cipherName;
650+
}
651+
652+
boolean matches(RSAESOAEPparams oaepParams) throws IOException
653+
{
654+
return Arrays.areEqual(derEncoding, getDEREncoding(oaepParams));
655+
}
656+
657+
private static RSAESOAEPparams createOAEPParams(ASN1ObjectIdentifier digestOID)
658+
{
659+
AlgorithmIdentifier hashAlgorithm = new AlgorithmIdentifier(digestOID, DERNull.INSTANCE);
660+
AlgorithmIdentifier maskGenAlgorithm = new AlgorithmIdentifier(PKCSObjectIdentifiers.id_mgf1, hashAlgorithm);
661+
return new RSAESOAEPparams(hashAlgorithm, maskGenAlgorithm, RSAESOAEPparams.DEFAULT_P_SOURCE_ALGORITHM);
662+
}
663+
664+
private static byte[] getDEREncoding(RSAESOAEPparams oaepParams) throws IOException
665+
{
666+
return oaepParams.getEncoded(ASN1Encoding.DER);
667+
}
668+
}
640669
}

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

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,7 @@ public class CMSTestUtil
5353
{
5454
public static SecureRandom rand;
5555
public static KeyPairGenerator kpg;
56+
public static KeyPairGenerator kpg_2048;
5657

5758
public static KeyPairGenerator gostKpg;
5859
public static KeyPairGenerator dsaKpg;
@@ -156,8 +157,8 @@ public class CMSTestUtil
156157
kpg = KeyPairGenerator.getInstance("RSA", "BC");
157158
kpg.initialize(1024, rand);
158159

159-
kpg = KeyPairGenerator.getInstance("RSA", "BC");
160-
kpg.initialize(1024, rand);
160+
kpg_2048 = KeyPairGenerator.getInstance("RSA", "BC");
161+
kpg_2048.initialize(2048, rand);
161162

162163
gostKpg = KeyPairGenerator.getInstance("GOST3410", "BC");
163164
GOST3410ParameterSpec gost3410P = new GOST3410ParameterSpec(CryptoProObjectIdentifiers.gostR3410_94_CryptoPro_A.getId());
@@ -278,6 +279,11 @@ public static KeyPair makeKeyPair()
278279
return kpg.generateKeyPair();
279280
}
280281

282+
public static KeyPair makeKeyPair_2048()
283+
{
284+
return kpg_2048.generateKeyPair();
285+
}
286+
281287
public static KeyPair makeGostKeyPair()
282288
{
283289
return gostKpg.generateKeyPair();

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

Lines changed: 37 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -130,8 +130,10 @@ public class NewEnvelopedDataTest
130130
private static String _reciDN;
131131
private static String _reciDN2;
132132
private static KeyPair _reciKP;
133+
private static KeyPair _reciKP_2048;
133134
private static KeyPair _reciOaepKP;
134135
private static X509Certificate _reciCert;
136+
private static X509Certificate _reciCert_2048;
135137
private static X509Certificate _reciCertOaep;
136138

137139
private static KeyPair _origEcKP;
@@ -594,7 +596,9 @@ private static void init()
594596
_reciDN = "CN=Doug, OU=Sales, O=Bouncy Castle, C=AU";
595597
_reciDN2 = "CN=Fred, OU=Sales, O=Bouncy Castle, C=AU";
596598
_reciKP = CMSTestUtil.makeKeyPair();
599+
_reciKP_2048 = CMSTestUtil.makeKeyPair_2048();
597600
_reciCert = CMSTestUtil.makeCertificate(_reciKP, _reciDN, _signKP, _signDN);
601+
_reciCert_2048 = CMSTestUtil.makeCertificate(_reciKP_2048, _reciDN, _signKP, _signDN);
598602
_reciCertOaep = CMSTestUtil.makeOaepCertificate(_reciKP, _reciDN, _signKP, _signDN);
599603

600604
_origEcKP = CMSTestUtil.makeEcDsaKeyPair();
@@ -1119,19 +1123,19 @@ public void testKeyTransOAEPSHA384()
11191123
doTestKeyTransOAEPDefaultNamed("SHA-384");
11201124
}
11211125

1122-
public void testKeyTransOAEPSHA1AndSHA256()
1126+
public void testKeyTransOAEPSHA512()
11231127
throws Exception
11241128
{
1125-
doTestKeyTransOAEPDefaultNamed("SHA-1", "SHA-256");
1129+
doTestKeyTransOAEPDefaultNamed_2048("SHA-512");
11261130
}
11271131

1128-
private void doTestKeyTransOAEPDefaultNamed(String digest)
1132+
public void testKeyTransOAEPSHA1AndSHA256()
11291133
throws Exception
11301134
{
1131-
doTestKeyTransOAEPDefaultNamed(digest, digest);
1135+
doTestKeyTransOAEPDefaultNamed("SHA-1", "SHA-256");
11321136
}
11331137

1134-
private void doTestKeyTransOAEPDefaultNamed(String digest, String mgfDigest)
1138+
private void doTestKeyTransOAEPDefaultNamed(String digest, String mgfDigest, X509Certificate reciCert, KeyPair reciKP)
11351139
throws Exception
11361140
{
11371141
byte[] data = "WallaWallaWashington".getBytes();
@@ -1142,8 +1146,8 @@ private void doTestKeyTransOAEPDefaultNamed(String digest, String mgfDigest)
11421146
OAEPParameterSpec oaepSpec = new OAEPParameterSpec(digest, "MGF1", new MGF1ParameterSpec(mgfDigest), new PSource.PSpecified(new byte[]{1, 2, 3, 4, 5}));
11431147
AlgorithmIdentifier oaepAlgId = paramsConverter.getAlgorithmIdentifier(PKCSObjectIdentifiers.id_RSAES_OAEP, oaepSpec);
11441148

1145-
edGen.addRecipientInfoGenerator(new JceKeyTransRecipientInfoGenerator(_reciCert, oaepAlgId).setProvider(BC));
1146-
edGen.addRecipientInfoGenerator(new JceKeyTransRecipientInfoGenerator(ASN1OctetString.getInstance(ASN1OctetString.getInstance(_reciCert.getExtensionValue(Extension.subjectKeyIdentifier.getId())).getOctets()).getOctets(), oaepAlgId, _reciCert.getPublicKey()).setProvider(BC));
1149+
edGen.addRecipientInfoGenerator(new JceKeyTransRecipientInfoGenerator(reciCert, oaepAlgId).setProvider(BC));
1150+
edGen.addRecipientInfoGenerator(new JceKeyTransRecipientInfoGenerator(ASN1OctetString.getInstance(ASN1OctetString.getInstance(reciCert.getExtensionValue(Extension.subjectKeyIdentifier.getId())).getOctets()).getOctets(), oaepAlgId, reciCert.getPublicKey()).setProvider(BC));
11471151

11481152
CMSEnvelopedData ed = edGen.generate(
11491153
new CMSProcessableByteArray(data),
@@ -1166,12 +1170,12 @@ private void doTestKeyTransOAEPDefaultNamed(String digest, String mgfDigest)
11661170

11671171
assertEquals(PKCSObjectIdentifiers.id_RSAES_OAEP, recipient.getKeyEncryptionAlgorithm().getAlgorithm());
11681172

1169-
byte[] recData = recipient.getContent(new JceKeyTransEnvelopedRecipient(_reciKP.getPrivate()).setProvider(BC));
1173+
byte[] recData = recipient.getContent(new JceKeyTransEnvelopedRecipient(reciKP.getPrivate()).setProvider(BC));
11701174

11711175
assertEquals(true, Arrays.equals(data, recData));
11721176
}
11731177

1174-
RecipientId id = new JceKeyTransRecipientId(_reciCert);
1178+
RecipientId id = new JceKeyTransRecipientId(reciCert);
11751179

11761180
Collection collection = recipients.getRecipients(id);
11771181
if (collection.size() != 2)
@@ -1181,6 +1185,30 @@ private void doTestKeyTransOAEPDefaultNamed(String digest, String mgfDigest)
11811185
assertTrue(collection.iterator().next() instanceof RecipientInformation);
11821186
}
11831187

1188+
private void doTestKeyTransOAEPDefaultNamed(String digest)
1189+
throws Exception
1190+
{
1191+
doTestKeyTransOAEPDefaultNamed(digest, digest);
1192+
}
1193+
1194+
private void doTestKeyTransOAEPDefaultNamed(String digest, String mgfDigest)
1195+
throws Exception
1196+
{
1197+
doTestKeyTransOAEPDefaultNamed(digest, digest, _reciCert, _reciKP);
1198+
}
1199+
1200+
private void doTestKeyTransOAEPDefaultNamed_2048(String digest)
1201+
throws Exception
1202+
{
1203+
doTestKeyTransOAEPDefaultNamed_2048(digest, digest);
1204+
}
1205+
1206+
private void doTestKeyTransOAEPDefaultNamed_2048(String digest, String mgfDigest)
1207+
throws Exception
1208+
{
1209+
doTestKeyTransOAEPDefaultNamed(digest, digest, _reciCert_2048, _reciKP_2048);
1210+
}
1211+
11841212
public void testKeyTransOAEPInCert()
11851213
throws Exception
11861214
{

0 commit comments

Comments
 (0)