输入对于RSA密码而言太大-我需要一个有效的内存替代方法来代替openssl cms解密

时间:2019-04-23 20:16:57

标签: c# encryption openssl

我有以下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命令一起使用,有人可以帮忙吗?让我知道是否还有任何不清楚的地方!

1 个答案:

答案 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]));
    }
}