简体   繁体   中英

How to decrypt RSA encrypted string from JavaScript in C#?

I have an asymmetric RSA key pair stored in two separate files. I want to generate a new symmetric key and encrypt it with public RSA key in my postbuild.js GULP script, so the user cannot access it. Then I want to send it to the C# server, where it would be decrypted and used.

I use the following JavaScript code in Node.js for encryption:

const generateAndEncryptKey = () => {
    const symmetricKey = crypto.randomBytes(32);
    const publicKey = fs.readFileSync("pubkey.pem", "utf8");
    const encryptedSymmetricKey = crypto.publicEncrypt({
        key: publicKey,
        padding: crypto.constants.RSA_PKCS1_OAEP_PADDING,
        oaepHash: "sha256",
    }, Buffer.from(symmetricKey)).toString("base64");
    return encryptedSymmetricKey;
}

The above code somehow works and generates a base64 string that I later send to the server. I'm not sure if this is the correct way to do this.

But I'm unable to find a way to decrypt this string in C#. I tried to use the BouncyCastle library and the following code:

public string DecryptKey(string encryptedKey) {
    var privateKey = @"-----BEGIN RSA PRIVATE KEY-----
...shortened...
-----END RSA PRIVATE KEY-----";

    var bytesToDecrypt = Convert.FromBase64String(encryptedKey);
    var decryptEngine = new Pkcs1Encoding(new RsaEngine());
    using (var txtreader = new StringReader(privateKey)) {
        AsymmetricCipherKeyPair keyPair = (AsymmetricCipherKeyPair)new PemReader(txtreader).ReadObject();
        decryptEngine.Init(false, keyPair.Private);
    }
    var decrypted = Encoding.UTF8.GetString(decryptEngine.ProcessBlock(bytesToDecrypt, 0, bytesToDecrypt.Length));
    return decrypted;
}

But the ProcessBlock method always throws an InvalidCipherTextException "unknown block type".

Can someone help me to find out what am I doing wrong or point me to another better way of achieving this?

Decryption with the C# code fails because in the NodeJS code OAEP /SHA256 is used as padding and in the C# code PKCS#1 v1.5 padding. For decryption to work, both paddings must be identical. The padding in the C# code can be adapted to that of the NodeJS code as follows:

var decryptEngine = new OaepEncoding(new RsaEngine(), new Sha256Digest());

Also, the decrypted key must not be UTF-8 decoded as this corrupts the data. Either it is returned as byte[] , or if conversion to a string is desired, a suitable binary-to-text encoding such as Base64 or hex must be used.

With these changes decryption works in the C# code.

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