如何extend/add一个用于CMS的Bouncycastle摘要算法?
How to extend/add a Bouncycastle digest algorithm for CMS?
使用 Java 我想使用 RSA 和 return byte[] signature
以 Cryptographic Message Syntax (CMS) 格式对给定的 byte[] hash
进行加密签名。
我为此目的使用 Bouncycastle Java API (BC) 并面临 NONEwithRSA
签名类型不存在的问题。 (java.lang.IllegalArgumentException: Unknown signature type requested: NONEWITHRSA
).
不幸的是,我无法更改输入或所需的输出格式,因此我需要 extend/add 现有的 BC 算法,以便我可以使用 NONEwithRSA
而不是所有其他现有的 (例如 SHA256withRSA
)。我该怎么做呢?我没有在 BC 文档中找到任何示例。
我想要的用法与此类似
byte[] doSigningCMS(byte[] data, X509Certificate cert, PrivateKey key) throws Exception {
CMSSignedDataGenerator signGen = new CMSSignedDataGenerator();
CMSTypedData content = new CMSProcessableByteArray(data);
ContentSigner signer = new JcaContentSignerBuilder("NONEwithRSA").build(key);
DigestCalculatorProvider dcp = new JcaDigestCalculatorProviderBuilder().build();
signGen.addSignerInfoGenerator(new JcaSignerInfoGeneratorBuilder(dcp).build(signer, cert));
return signGen.generate(content, false).getEncoded();
}
到目前为止我尝试了什么
- 使用 "copying" 一堆 BC 代码和 "fake"
SHA256withRSA
添加我自己的 JCA 提供程序,基本上 return 一个 NoneDigest
而不是 SHA256Digest
。但这似乎是非常错误的。
- 用
((BouncyCastleProvider) Security.getProvider("BC")).addAlgorithm(ALG_ALIAS, NoneDigest.class.getName())
将我自己的算法添加到 BC 似乎不起作用(未找到算法)
我希望得到一些建议和指导来做到这一点(如果可能的话)"the right way"。谢谢。
"NoneWithRSA"是不加摘要算法OID的RSA数字签名。密码提供者也不制作摘要。基本上它是使用私钥的 PKCS#1_v15 加密。
您可以在这个 OpenJDK 测试中看到它是如何工作的https://github.com/ddopson/openjdk-test/blob/master/java/security/Signature/NONEwithRSA.java
由于 Bouncycastle 似乎不支持它,我认为您可以使用默认提供程序而不是使用 JcaContentSignerBuilder
来提供您自己的 ContentSigner 实现
假设输入数据已经被散列,所以如果你做的是PKCS#1签名,我想你需要提供签名算法。查看 RFC3477 它取决于所使用的哈希算法。
A.2.4 RSASSA-PKCS1-v1_5
The object identifier for RSASSA-PKCS1-v1_5 shall be one of the
following. The choice of OID depends on the choice of hash
algorithm: MD2, MD5, SHA-1, SHA-256, SHA-384, or SHA-512.
String sigAlgo = "SHA256WithRSAEncryption"; // "SHA256WithRSAEncryption" for SHA256, "SHA1WithRSAEncryption" for SHA1, etc.
ContentSigner signer = new CustomContentSigner(key, sigAlgo );
public class CustomContentSigner implements ContentSigner {
private AlgorithmIdentifier algorithmIdentifier;
private Signature signature;
private ByteArrayOutputStream outputStream;
public CustomContentSigner(PrivateKey privateKey, String sigAlgo) {
//Utils.throwIfNull(privateKey, sigAlgo);
this.algorithmIdentifier = new DefaultSignatureAlgorithmIdentifierFinder().find(sigAlgo);
try {
this.outputStream = new ByteArrayOutputStream();
this.signature = Signature.getInstance("NONEwithRSA");
this.signature.initSign(privateKey);
} catch (GeneralSecurityException gse) {
throw new IllegalArgumentException(gse.getMessage());
}
}
@Override
public AlgorithmIdentifier getAlgorithmIdentifier() {
return algorithmIdentifier;
}
@Override
public OutputStream getOutputStream() {
return outputStream;
}
@Override
public byte[] getSignature() {
try {
signature.update(outputStream.toByteArray());
return signature.sign();
} catch (GeneralSecurityException gse) {
gse.printStackTrace();
return null;
}
}
}
免责声明:我不知道它是否有效,但您可以尝试一下
使用 Java 我想使用 RSA 和 return byte[] signature
以 Cryptographic Message Syntax (CMS) 格式对给定的 byte[] hash
进行加密签名。
我为此目的使用 Bouncycastle Java API (BC) 并面临 NONEwithRSA
签名类型不存在的问题。 (java.lang.IllegalArgumentException: Unknown signature type requested: NONEWITHRSA
).
不幸的是,我无法更改输入或所需的输出格式,因此我需要 extend/add 现有的 BC 算法,以便我可以使用 NONEwithRSA
而不是所有其他现有的 (例如 SHA256withRSA
)。我该怎么做呢?我没有在 BC 文档中找到任何示例。
我想要的用法与此类似
byte[] doSigningCMS(byte[] data, X509Certificate cert, PrivateKey key) throws Exception {
CMSSignedDataGenerator signGen = new CMSSignedDataGenerator();
CMSTypedData content = new CMSProcessableByteArray(data);
ContentSigner signer = new JcaContentSignerBuilder("NONEwithRSA").build(key);
DigestCalculatorProvider dcp = new JcaDigestCalculatorProviderBuilder().build();
signGen.addSignerInfoGenerator(new JcaSignerInfoGeneratorBuilder(dcp).build(signer, cert));
return signGen.generate(content, false).getEncoded();
}
到目前为止我尝试了什么
- 使用 "copying" 一堆 BC 代码和 "fake"
SHA256withRSA
添加我自己的 JCA 提供程序,基本上 return 一个NoneDigest
而不是SHA256Digest
。但这似乎是非常错误的。 - 用
((BouncyCastleProvider) Security.getProvider("BC")).addAlgorithm(ALG_ALIAS, NoneDigest.class.getName())
将我自己的算法添加到 BC 似乎不起作用(未找到算法)
我希望得到一些建议和指导来做到这一点(如果可能的话)"the right way"。谢谢。
"NoneWithRSA"是不加摘要算法OID的RSA数字签名。密码提供者也不制作摘要。基本上它是使用私钥的 PKCS#1_v15 加密。
您可以在这个 OpenJDK 测试中看到它是如何工作的https://github.com/ddopson/openjdk-test/blob/master/java/security/Signature/NONEwithRSA.java
由于 Bouncycastle 似乎不支持它,我认为您可以使用默认提供程序而不是使用 JcaContentSignerBuilder
假设输入数据已经被散列,所以如果你做的是PKCS#1签名,我想你需要提供签名算法。查看 RFC3477 它取决于所使用的哈希算法。
A.2.4 RSASSA-PKCS1-v1_5
The object identifier for RSASSA-PKCS1-v1_5 shall be one of the following. The choice of OID depends on the choice of hash algorithm: MD2, MD5, SHA-1, SHA-256, SHA-384, or SHA-512.
String sigAlgo = "SHA256WithRSAEncryption"; // "SHA256WithRSAEncryption" for SHA256, "SHA1WithRSAEncryption" for SHA1, etc.
ContentSigner signer = new CustomContentSigner(key, sigAlgo );
public class CustomContentSigner implements ContentSigner {
private AlgorithmIdentifier algorithmIdentifier;
private Signature signature;
private ByteArrayOutputStream outputStream;
public CustomContentSigner(PrivateKey privateKey, String sigAlgo) {
//Utils.throwIfNull(privateKey, sigAlgo);
this.algorithmIdentifier = new DefaultSignatureAlgorithmIdentifierFinder().find(sigAlgo);
try {
this.outputStream = new ByteArrayOutputStream();
this.signature = Signature.getInstance("NONEwithRSA");
this.signature.initSign(privateKey);
} catch (GeneralSecurityException gse) {
throw new IllegalArgumentException(gse.getMessage());
}
}
@Override
public AlgorithmIdentifier getAlgorithmIdentifier() {
return algorithmIdentifier;
}
@Override
public OutputStream getOutputStream() {
return outputStream;
}
@Override
public byte[] getSignature() {
try {
signature.update(outputStream.toByteArray());
return signature.sign();
} catch (GeneralSecurityException gse) {
gse.printStackTrace();
return null;
}
}
}
免责声明:我不知道它是否有效,但您可以尝试一下