简体   繁体   中英

RSA: Using public key for decryption in .NET?

I'm having issues with the RSA encryption/decryption capabilities of MS .NET:

It seems, .NET does not support using a private key for encryption and the corresponding public key for decryption. (As I understand, doing it that way round, somehow infringes the security of the algorithm.)

Ok, but for example when I sign an assembly on building, it seems the compiler just does that : "The compiler encrypts the digest using the 1024-bit private key from your public-private key pair file."

So, if I cannot convince the RSACryptoServiceProvider to use a public key for decrypting, how can I achieve something similar like the compiler?

I just want to encrypt a few bytes with my private key and decrypt it with the public key, for some non-critical task. If a programming geek manages to break that scheme, I'll live. I just want to prevent the non-tech-savvy John Doe from snooping around.

Any advice on this would be appreciated.

Greets berntie

Edit: Usign SignData() and VerifySign() has been suggested, but then I can only compare hashes for equality. However, I need to retrieve the original input that was encrypted/signed.

.Net does support it, but that concept is called "Signing" and uses the SignData() method of RSACryptoServiceProvider . Technically, what's happening is it's creating a hash of the data to be signed, then encrypting that hash with the private key.

I think the reason they don't support arbitrarily encrypting with the private key is to ensure good security practices in your code, so that you don't accidentally encrypt with the wrong key, or that you don't use an insecure technique for making the signature.

See the documentation on SignData for example code.

Here is my code, still has some defect but worked in most situation. I get modulusString by Java.

public static string Decrypt(string text, string modulusString)
{
    var modulus = BigInteger.Parse(modulusString);
    var exponent = BigInteger.Parse("65537");

    var encryptBytes = Convert.FromBase64String(text);

    if (publicKey.Modulus.Length > 309) // long enough key to decrypt short message
    {
        return Decrypt(encryptBytes, exponent, modulus);
    }

    string result = string.Empty;
    int i = 0;
    while (i < encryptBytes.Length) // for short key, must decrypt section-by-section
    {
        var temp = new byte[Math.Min(encryptBytes.Length, 128)];
        Array.Copy(encryptBytes, i, temp, 0, temp.Length);
        result += Decrypt(temp, exponent, modulus);
        i += 128;
    }
    return result;
}

private static string Decrypt(byte[] encryptBytes, BigInteger exponent, BigInteger modulus)
{
    Array.Reverse(encryptBytes); // BigIntenger need little-endian
    if ((encryptBytes[encryptBytes.Length - 1] & 0x80) > 0) // make positive
    {
        var temp = new byte[encryptBytes.Length];
        Array.Copy(encryptBytes, temp, encryptBytes.Length);
        encryptBytes = new byte[temp.Length + 1];
        Array.Copy(temp, encryptBytes, temp.Length);
    }
    var value = new BigInteger(encryptBytes);

    var result = BigInteger.ModPow(value, exponent, modulus);
    byte[] resultBytes = result.ToByteArray();
    Array.Reverse(resultBytes);

    int index = Array.FindIndex(resultBytes, b => b == 0) + 1;
    return Encoding.UTF8.GetString(resultBytes, index, resultBytes.Length - index);
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM