Skip to content

Commit

Permalink
CMS: Add support for sha-1WithRSAEncryption and other (aliases) diges…
Browse files Browse the repository at this point in the history
…t algorithm.

Per RFC 3279 / RFC 8017, this digest algorithm computes the SHA-1 digest on the encoded `DigestInfo` whose `digestAlgorithm` is set to the `id-sha1` OID.
  • Loading branch information
kevinhwang committed Oct 3, 2023
1 parent e007cbe commit b0f9377
Show file tree
Hide file tree
Showing 3 changed files with 75 additions and 24 deletions.
24 changes: 23 additions & 1 deletion pkix/src/main/java/org/bouncycastle/cms/SignerInformation.java
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@
import java.util.Enumeration;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.HashMap;

import org.bouncycastle.asn1.ASN1Encodable;
import org.bouncycastle.asn1.ASN1EncodableVector;
Expand All @@ -24,6 +26,7 @@
import org.bouncycastle.asn1.cms.SignerIdentifier;
import org.bouncycastle.asn1.cms.SignerInfo;
import org.bouncycastle.asn1.cms.Time;
import org.bouncycastle.asn1.oiw.OIWObjectIdentifiers;
import org.bouncycastle.asn1.x509.AlgorithmIdentifier;
import org.bouncycastle.asn1.x509.DigestInfo;
import org.bouncycastle.cert.X509CertificateHolder;
Expand All @@ -39,6 +42,14 @@
*/
public class SignerInformation
{
private static final Map<ASN1ObjectIdentifier, ASN1ObjectIdentifier> digestOidMap = new HashMap<>();

static {
// sha-1WithRSAEncryption (RFC 3279 2.2.1)
digestOidMap.put(OIWObjectIdentifiers.sha1WithRSA, OIWObjectIdentifiers.idSHA1);
// sha-1WithRSASignature (RFC 8017 A.2.4)
digestOidMap.put(new ASN1ObjectIdentifier("1.2.840.113549.1.1.5"), OIWObjectIdentifiers.idSHA1);
}
private final SignerId sid;
private final CMSProcessable content;
private final byte[] signature;
Expand Down Expand Up @@ -460,7 +471,7 @@ else if (signedAttributeSet != null)

if (encName.equals("RSA"))
{
DigestInfo digInfo = new DigestInfo(new AlgorithmIdentifier(digestAlgorithm.getAlgorithm(), DERNull.INSTANCE), resultDigest);
DigestInfo digInfo = new DigestInfo(new AlgorithmIdentifier(digestAlgorithmForDigestInfoDataEncoding(), DERNull.INSTANCE), resultDigest);

return rawVerifier.verify(digInfo.getEncoded(ASN1Encoding.DER), this.getSignature());
}
Expand All @@ -477,6 +488,17 @@ else if (signedAttributeSet != null)
}
}

/**
* Computes the `digestAlgorithm (DigestAlgorithmIdentifier)` field of the `DigestInfo` as specified in
* RFC 2313 10.1.2.
* This pertains to the digest algorithm, not signature algorithm.
*/
private ASN1ObjectIdentifier digestAlgorithmForDigestInfoDataEncoding() {
ASN1ObjectIdentifier originalAlgorithm = digestAlgorithm.getAlgorithm();
ASN1ObjectIdentifier digestAlgorithmForDataEncoding = digestOidMap.get(originalAlgorithm);
return digestAlgorithmForDataEncoding != null ? digestAlgorithmForDataEncoding : originalAlgorithm;
}

/**
* RFC 3852 11.1 Check the content-type attribute is correct
*
Expand Down
71 changes: 48 additions & 23 deletions pkix/src/test/java/org/bouncycastle/cms/test/NewSignedDataTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.Set;

import junit.framework.Assert;
Expand Down Expand Up @@ -1590,70 +1591,86 @@ public void testSHA3_384WithRSAPSS()
rsaPSSTest("SHA3-384withRSAandMGF1");
}

public void testSHA1WithRSADigest()
public void testSHA1WithRSASignature()
throws Exception
{
rsaDigestTest("SHA1withRSA");
rsaSignatureTest("SHA1withRSA");
}

public void testSHA224WithRSADigest()
public void testSHA256WithRSASignatureAndSHA1WithRSAEncryptionDigest()
throws Exception
{
rsaSignatureAndDigestTest("SHA256withRSA",
// sha-1WithRSAEncryption (RFC 3279 2.2.1)
Optional.of(new AlgorithmIdentifier(new ASN1ObjectIdentifier("1.3.14.3.2.29"))));
}

public void testSHA256WithRSASignatureAndSHA1WithRSASignatureDigest()
throws Exception
{
rsaSignatureAndDigestTest("SHA256withRSA",
// sha-1WithRSASignature (RFC 8017 A.2.4)
Optional.of(new AlgorithmIdentifier(new ASN1ObjectIdentifier("1.2.840.113549.1.1.5"))));
}

public void testSHA224WithRSASignature()
throws Exception
{
rsaDigestTest("SHA224withRSA");
rsaSignatureTest("SHA224withRSA");
}

public void testSHA256WithRSADigest()
public void testSHA256WithRSASignature()
throws Exception
{
rsaDigestTest("SHA256withRSA");
rsaSignatureTest("SHA256withRSA");
}

public void testSHA384WithRSADigest()
public void testSHA384WithRSASignature()
throws Exception
{
rsaDigestTest("SHA384withRSA");
rsaSignatureTest("SHA384withRSA");
}

public void testSHA512WithRSADigest()
public void testSHA512WithRSASignature()
throws Exception
{
rsaDigestTest("SHA512withRSA");
rsaSignatureTest("SHA512withRSA");
}

public void testSHA3_224WithRSADigest()
public void testSHA3_224WithRSASignature()
throws Exception
{
rsaDigestTest("SHA3-224withRSA");
rsaSignatureTest("SHA3-224withRSA");
}

public void testSHA3_256WithRSADigest()
public void testSHA3_256WithRSASignature()
throws Exception
{
rsaDigestTest("SHA3-256withRSA");
rsaSignatureTest("SHA3-256withRSA");
}

public void testSHA3_384WithRSADigest()
public void testSHA3_384WithRSASignature()
throws Exception
{
rsaDigestTest("SHA3-384withRSA");
rsaSignatureTest("SHA3-384withRSA");
}

public void testSHA3_512WithRSADigest()
public void testSHA3_512WithRSASignature()
throws Exception
{
rsaDigestTest("SHA3-512withRSA");
rsaSignatureTest("SHA3-512withRSA");
}

public void testSHA512_224ithRSADigest()
public void testSHA512_224ithRSASignature()
throws Exception
{
rsaDigestTest("SHA512(224)withRSA");
rsaSignatureTest("SHA512(224)withRSA");
}

public void testSHA512_256ithRSADigest()
public void testSHA512_256ithRSASignature()
throws Exception
{
rsaDigestTest("SHA512(256)withRSA");
rsaSignatureTest("SHA512(256)withRSA");
}

public void testEd25519()
Expand Down Expand Up @@ -2174,8 +2191,14 @@ private void rsaPSSTest(String signatureAlgorithmName)
verifySignatures(s, md.digest("Hello world!".getBytes()));
}

private void rsaDigestTest(String signatureAlgorithmName)
private void rsaSignatureTest(String signatureAlgorithmName)
throws Exception
{
rsaSignatureAndDigestTest(signatureAlgorithmName, Optional.empty());
}

private void rsaSignatureAndDigestTest(String signatureAlgorithmName, Optional<AlgorithmIdentifier> digestAlgorithm)
throws Exception
{
List certList = new ArrayList();
CMSTypedData msg = new CMSProcessableByteArray("Hello world!".getBytes());
Expand All @@ -2193,6 +2216,8 @@ private void rsaDigestTest(String signatureAlgorithmName)

gen.addSignerInfoGenerator(siBuilder.build(contentSigner, _origCert));

digestAlgorithm.ifPresent(siBuilder::setContentDigest);

gen.addCertificates(certs);

CMSSignedData s = gen.generate(msg, false);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,10 @@ public class MessageDigestUtils
digestOidMap.put(NISTObjectIdentifiers.id_shake256, "SHAKE256");
digestOidMap.put(GMObjectIdentifiers.sm3, "SM3");
digestOidMap.put(MiscObjectIdentifiers.blake3_256, "BLAKE3-256");
// sha-1WithRSAEncryption (RFC 3279 2.2.1)
digestOidMap.put(OIWObjectIdentifiers.sha1WithRSA, "SHA-1");
// sha-1WithRSASignature (RFC 8017 A.2.4)
digestOidMap.put(new ASN1ObjectIdentifier("1.2.840.113549.1.1.5"), "SHA-1");

digestAlgIdMap.put("SHA-1", new AlgorithmIdentifier(OIWObjectIdentifiers.idSHA1, DERNull.INSTANCE));
digestAlgIdMap.put("SHA-224", new AlgorithmIdentifier(NISTObjectIdentifiers.id_sha224));
Expand Down

0 comments on commit b0f9377

Please sign in to comment.