在站点上找到的RSA加密和解密脚本不适用于在此站点上找到的密钥对生成脚本

时间:2018-09-27 04:35:02

标签: c# encryption cryptography rsa public-key-encryption

由于我正在做一个需要RSA加密和解密的Unity项目,因此我在一个可以执行在Unity中工作的PEM加密和解密的站点中找到了以下代码:

using System.Security.Cryptography;
using System.Text;
using System;

public class RSAHelper
{
    public static string Encript(string value, string pemPublicKey)
    {
        using(RSACryptoServiceProvider rsa = new RSACryptoServiceProvider())
        {
            rsa.ImportParameters(ConvertFromPemPublicKey(pemPublicKey));
            var encryptedBytes = rsa.Encrypt(Encoding.UTF8.GetBytes(value), false);
            return Convert.ToBase64String(encryptedBytes);
        }
    }

    public static string Decrypt(string encryptedData, string pemPrivateKey)
    {
        using(RSACryptoServiceProvider rsa = new RSACryptoServiceProvider())
        {
            rsa.ImportParameters(ConvertFromPemPrivateKey(pemPrivateKey));
            var data = rsa.Decrypt(Convert.FromBase64String(encryptedData), false);
            return Encoding.UTF8.GetString(data, 0, data.Length);
        }
    }

    // http://blog.csdn.net/liguo9860/article/details/40922919
    //
    public static RSAParameters ConvertFromPemPublicKey(string pemFileConent)  
    {  
        pemFileConent = pemFileConent.Replace("-----BEGIN PUBLIC KEY-----", "").Replace("-----END PUBLIC KEY-----", "").Replace("\n", "").Replace("\r", "");  
        byte[] keyData = Convert.FromBase64String(pemFileConent);  
        bool keySize1024 = (keyData.Length == 162);  
        bool keySize2048 = (keyData.Length == 294);  
        if (!(keySize1024 || keySize2048))  
        {  
            throw new ArgumentException("pem file content is incorrect, Only support the key size is 1024 or 2048");  
        }  
        byte[] pemModulus = (keySize1024 ? new byte[128] : new byte[256]);  
        var pemPublicExponent = new byte[3];  
        Array.Copy(keyData, (keySize1024 ? 29 : 33), pemModulus, 0, (keySize1024 ? 128 : 256));  
        Array.Copy(keyData, (keySize1024 ? 159 : 291), pemPublicExponent, 0, 3);  
        var para = new RSAParameters { Modulus = pemModulus, Exponent = pemPublicExponent };  
        return para;  
    }  

    public static RSAParameters ConvertFromPemPrivateKey(string pemFileConent)
    {
        if (string.IsNullOrEmpty(pemFileConent))
        {
            throw new ArgumentNullException("pemFileConent", "This arg cann't be empty.");
        }

        pemFileConent = pemFileConent.Replace("-----BEGIN RSA PRIVATE KEY-----", "").Replace("-----END RSA PRIVATE KEY-----", "").Replace("\n", "").Replace("\r", "");
        byte[] keyData = Convert.FromBase64String(pemFileConent);
        bool keySize1024 = (keyData.Length == 609 || keyData.Length == 610);
        bool keySize2048 = (keyData.Length == 1190 || keyData.Length == 1192);

        if (!(keySize1024 || keySize2048))
        {
            throw new ArgumentException("pem file content is incorrect, Only support the key size is 1024 or 2048");
        }

        int index = (keySize1024 ? 11 : 12);
        byte[] pemModulus = (keySize1024 ? new byte[128] : new byte[256]);
        Array.Copy(keyData, index, pemModulus, 0, pemModulus.Length);

        index += pemModulus.Length;
        index += 2;
        var pemPublicExponent = new byte[3];
        Array.Copy(keyData, index, pemPublicExponent, 0, 3);

        index += 3;
        index += 4;
        if (keyData[index] == 0)
        {
            index++;
        }
        byte[] pemPrivateExponent = (keySize1024 ? new byte[128] : new byte[256]);
        Array.Copy(keyData, index, pemPrivateExponent, 0, pemPrivateExponent.Length);

        index += pemPrivateExponent.Length;
        index += (keySize1024 ? ((int)keyData[index + 1] == 64 ? 2 : 3) : ((int)keyData[index + 2] == 128 ? 3 : 4));
        byte[] pemPrime1 = (keySize1024 ? new byte[64] : new byte[128]);
        Array.Copy(keyData, index, pemPrime1, 0, pemPrime1.Length);

        index += pemPrime1.Length;
        index += (keySize1024 ? ((int)keyData[index + 1] == 64 ? 2 : 3) : ((int)keyData[index + 2] == 128 ? 3 : 4));
        byte[] pemPrime2 = (keySize1024 ? new byte[64] : new byte[128]);
        Array.Copy(keyData, index, pemPrime2, 0, pemPrime2.Length);

        index += pemPrime2.Length;
        index += (keySize1024 ? ((int)keyData[index + 1] == 64 ? 2 : 3) : ((int)keyData[index + 2] == 128 ? 3 : 4));
        byte[] pemExponent1 = (keySize1024 ? new byte[64] : new byte[128]);
        Array.Copy(keyData, index, pemExponent1, 0, pemExponent1.Length);

        index += pemExponent1.Length;
        index += (keySize1024 ? ((int)keyData[index + 1] == 64 ? 2 : 3) : ((int)keyData[index + 2] == 128 ? 3 : 4));
        byte[] pemExponent2 = (keySize1024 ? new byte[64] : new byte[128]);
        Array.Copy(keyData, index, pemExponent2, 0, pemExponent2.Length);

        index += pemExponent2.Length;
        index += (keySize1024 ? ((int)keyData[index + 1] == 64 ? 2 : 3) : ((int)keyData[index + 2] == 128 ? 3 : 4));
        byte[] pemCoefficient = (keySize1024 ? new byte[64] : new byte[128]);
        Array.Copy(keyData, index, pemCoefficient, 0, pemCoefficient.Length);

        var para = new RSAParameters
            {
                Modulus = pemModulus,
                Exponent = pemPublicExponent,
                D = pemPrivateExponent,
                P = pemPrime1,
                Q = pemPrime2,
                DP = pemExponent1,
                DQ = pemExponent2,
                InverseQ = pemCoefficient
            };
        return para;
    }
}

此外,在项目中,由于我将要做一些类似的事情,例如自行生成PEM密钥对,因此我在this questionthis question中找到了可以做到这一点的代码。但是,将它们放在一起后,问题是,生成的密钥无法用于加密。这是我使用上面的代码生成密钥对的方式:

CspParameters csp = new CspParameters
    {
        ProviderType = 1
    };
RSACryptoServiceProvider rsa = new RSACryptoServiceProvider(2048, csp);
RSAHelper.GetKeyPairs(rsa, out publicKey, out privateKey);

GetKeyPairs方法如下:

public static void GetKeyPairs(RSACryptoServiceProvider rsa, out string publicKey, out string privateKey)
    {
        try
        {
            StringWriter publicKeyWriter = new StringWriter();
            ExportPublicKey(rsa, publicKeyWriter);
            StringWriter privateKeyWriter = new StringWriter();
            ExportPrivateKey(rsa, privateKeyWriter);
            publicKey = publicKeyWriter.ToString();
            privateKey = privateKeyWriter.ToString();
        }
        catch (Exception e)
        {
            throw new ArgumentException("Generating key pairs unsuccessfully!");
        }
    }

在这种情况下我做错了什么?

0 个答案:

没有答案