我有以下openssl命令,它可以很好地用我拥有的RSA私钥解密.mp3.bin加密文件,效果很好:
openssl.exe cms -decrypt -inform DER -in {inFilePath} -binary -inkey {privateKey} -out {outFilePath}
我遇到的问题是,这似乎只能用于本地计算机上已经存在的文件。我正在寻找一种执行相同解密但在内存中的方法,我想在我的程序内存中解密云中的文件,然后将内存中的解密流写入云中的另一个位置。上面的命令似乎只适用于可以在本地驱动器中找到的本地文件。
我研究了充气城堡和其他选项,但没有发现任何有效的方法。我有以下代码,但返回错误:“未处理的异常:Org.BouncyCastle.Crypto.DataLengthException:输入的RSA密码太大。”现在,我只是在测试解密本地计算机上已经存在的内存中的文件。
AsymmetricKeyParameter privateKey = getPrivateKey(privateKeyFileName);
RsaEngine e = new RsaEngine();
e.Init(false, privateKey);
byte[] decryptedAudioFile = File.ReadAllBytes(binFileName);
byte[] decrypted = e.ProcessBlock(decryptedAudioFile, 0, decryptedAudioFile.Length);
static AsymmetricKeyParameter getPrivateKey(string privateKeyFileName)
{
AsymmetricCipherKeyPair keyPair;
using(var reader = File.OpenText(privateKeyFileName))
{
keyPair = (AsymmetricCipherKeyPair)new PemReader(reader).ReadObject();
}
return keyPair.Private;
}
我不是很确定为什么错误说明输入对于RSA密钥来说太大,因为它可以与前面提到的openssl cms命令一起使用,有人可以帮忙吗?让我知道是否还有任何不清楚的地方!
答案 0 :(得分:2)
您应该使用Bouncy Castle的CMS库进行这种解密。 CMS中使用的RSA不仅是RSA,而且是容器结构中的RSA + AES。搜索CmsEnvelopedDataParser
以获取更多信息。
请注意,Microsoft API也直接支持CMS,在这种情况下,请搜索EnvelopedCms
。
当前您正在直接使用RSA,对于大量数据,它确实不能直接使用-绝对不切实际。
设置Bouncy C#对我来说有点麻烦,但是如果我用Java提供源代码,那么您应该能够在C#中使用大致相同的类。最大的把戏是可能的密钥/ Receipient
处理。
/**
* <pre>
* openssl genrsa -out rsaprivkey.pem 2048
* openssl pkcs8 -topk8 -nocrypt -in rsaprivkey.pem -out privkey.pem
* openssl req -x509 -key privkey.pem -out encrypt.cer
* openssl cms -encrypt -binary -in plain.txt -outform DER -out enveloped.p7 encrypt.cer
* openssl cms -decrypt -binary -inform DER -in enveloped.p7 -out decrypted_openssl.txt -inkey privkey.pem
* </pre>
*
* @author maartenb
*/
public class DecryptRSACms {
private static void decrypt(PrivateKey privateKey, File encrypted, File decryptedDestination)
throws IOException, CMSException {
byte[] encryptedData = Files.readAllBytes(encrypted.toPath());
CMSEnvelopedDataParser parser = new CMSEnvelopedDataParser(encryptedData);
RecipientInformation recInfo = getSingleRecipient(parser);
Recipient recipient = new JceKeyTransEnvelopedRecipient(privateKey);
try (InputStream decryptedStream = recInfo.getContentStream(recipient).getContentStream()) {
Files.copy(decryptedStream, decryptedDestination.toPath());
}
System.out.println(String.format("Decrypted '%s' to '%s'", encrypted.getAbsolutePath(),
decryptedDestination.getAbsolutePath()));
}
private static RecipientInformation getSingleRecipient(CMSEnvelopedDataParser parser) {
Collection<RecipientInformation> recInfos = parser.getRecipientInfos().getRecipients();
Iterator<RecipientInformation> recipientIterator = recInfos.iterator();
if (!recipientIterator.hasNext()) {
throw new RuntimeException("Could not find recipient");
}
return (RecipientInformation) recipientIterator.next();
}
private static RSAPrivateKey parsePrivateKey(File privateKeyPEM) throws IOException, InvalidKeySpecException {
PemObject readPemObject;
try (PEMParser parser = new PEMParser(new FileReader(privateKeyPEM))) {
readPemObject = parser.readPemObject();
}
System.out.println(readPemObject.getType());
byte[] pkcs8KeyData = readPemObject.getContent();
PKCS8EncodedKeySpec privKeySpec = new PKCS8EncodedKeySpec(pkcs8KeyData);
KeyFactory kf;
try {
kf = KeyFactory.getInstance("RSA");
} catch (NoSuchAlgorithmException e) {
throw new RuntimeException(e);
}
PrivateKey privKey = kf.generatePrivate(privKeySpec);
return (RSAPrivateKey) privKey;
}
public static void main(String[] args) throws Exception {
RSAPrivateKey rsaPrivateKey = parsePrivateKey(new File(args[0]));
decrypt(rsaPrivateKey, new File(args[1]), new File(args[2]));
}
}