javascript c# 간의 암호화 (RSA 와 JSEncrypt 를 이용)

2023. 2. 6. 00:00CSharp

반응형

jsencrypt 와 dotnet 7 RSA 간에 암호화 처리에 어려움이 있다. 

 

jsencrypt 는 openssl 을 기반으로 pem 형태의 pkcs1 encoding 을 사용하여 data 를 encrypt 하고 decrypt 한다. 

 

그런데 c# 이 이 pem 형태의 key 를 생성해도 실제 jsencrypt 는 제대로 처리 하지 못한다. 

 

이문제를 처리하기 위한 코드이다. 

 

javascript 그 코드를 사용하여 처리 한다. 

//let publickey ="-----BEGIN PUBLIC KEY-----\n";
const publickey =  `-----BEGIN PUBLIC KEY-----
MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDZkPU9wKqarE4GUfBXgSOQGeef
NPZzE/74vIX3m5DgPKyHZTv1fuhGSG0gzUe2E+BDpGrpgzucH9selqzR5nmWepHg
XKgtbqi9dx/AdcW9kj7aSqyVgl68RSBFCBXz7XRF/sJzMkWDjwFLKv3sXyYyWxm7
lWkJ1nMIijuOEFPe7QIDAQAB
-----END PUBLIC KEY-----`;
//publickey +="\n-----END PUBLIC KEY-----";

console.log(publickey);
const privatekey = `-----BEGIN PRIVATE KEY-----
MIICdQIBADANBgkqhkiG9w0BAQEFAASCAl8wggJbAgEAAoGBANmQ9T3AqpqsTgZR
8FeBI5AZ55809nMT/vi8hfebkOA8rIdlO/V+6EZIbSDNR7YT4EOkaumDO5wf2x6W
rNHmeZZ6keBcqC1uqL13H8B1xb2SPtpKrJWCXrxFIEUIFfPtdEX+wnMyRYOPAUsq
/exfJjJbGbuVaQnWcwiKO44QU97tAgMBAAECgYA9ZuvPwdBkVryui/GIwKmIwcbc
59WmJL6Q9KPafc0le/o1PBzv7CEhtM8XstfKS1G/xWdm/+KS7Wqp91xO4PzvNZxT
s+kGd6X6nAmdMj1rlxAvLjRK7nr/xTaWdEN6zxM7gbnnVYIHl9VZ+iQ2hG0WxD5q
EbOWJA8SIttGhsCfAQJBAP1aA4n8dA39SaJAu73ReNVJblTgLWIAjyPsgSSBIueQ
nhQIX+E45CrOYgYtkWDBedq0JCIvYtQRfy5BhcJwFOcCQQDb1y4XzzwGlmIWXOXF
wkAGiibjl1pboqErFGD4e1y5g9d18jL+GJ8IjztPW6P0KBvqZrjjUCHPX+aQfzeq
zR8LAkAJ0LHwZ5prbFOs+IsNeI8Q3E5s9V5svI7PGnuKWYJrrDujlQt540VbrzE3
Ag7uy7AX3ADGXkWa566gsSMofEUjAkBtEsInxgY+LnbUKZtHFy21EO5ilUGbnYDh
YucJ4gsLcEKCnnx2XbjqAkanBQy/ovbWwciR37wmq6o1nyj7cXIpAkBSBVbi7HFC
x/xOjyi4A6IidWO6OockKvlgB3JDBMwnWpID8xes6MsO8yAOs1KXWCXR0EM5FrGI
vguNCuiFODZh
-----END PRIVATE KEY-----`

//var keyBytes = CryptoJS.PBKDF2('80808080808080808080808080808080', '8080808080808080', { keySize: 256 / 8, iterations: 1000, hasher: CryptoJS.algo.SHA512 });
// take first 32 bytes as key (like in C# code)
//const aesKey = new CryptoJS.lib.WordArray.init(keyBytes.words, 32);
const data = "1234Abcd 얼씨구리 절씨구리    지화자 蘭復a";
//console.log(aesKey.toString());
var encrypt  = new JSEncrypt();
//new JSEncrypt({
//    default_key_size: 2048
//  })
encrypt.setPublicKey(publickey); 
const encryptedAesKey = encrypt.encrypt(data);
var rsaDecrypt = new JSEncrypt();
rsaDecrypt.setPrivateKey(privatekey); 
const decryptedAesKey = rsaDecrypt.decrypt(encryptedAesKey);
console.log(encryptedAesKey);
console.log(decryptedAesKey);

c# 은 다음과 같이 encrypt decrypt 한다. 

 

 public static byte[] _aesKey;

    public static string EncryptAesKeyDynamicKey(byte[] aesKey, string publicKey, string password = "")
    {       
        using var rsa = RSA.Create();
        rsa.ImportFromPem(publicKey);
        var encryptedAesKey = rsa?.Encrypt(aesKey, RSAEncryptionPadding.Pkcs1);
        
        if (encryptedAesKey == null) throw new NullReferenceException(nameof(encryptedAesKey));

        return Convert.ToBase64String(encryptedAesKey);
    }
    public static string DecryptAesKeyDynamicKey(byte[] encryptedAesKey, string privateKey, string password = "")
    {
        using var rsa = RSA.Create();
        rsa.ImportFromPem(privateKey);
        var decryptedAesKey = rsa?.Decrypt(encryptedAesKey, RSAEncryptionPadding.Pkcs1);
        if (decryptedAesKey == null) throw new NullReferenceException(nameof(decryptedAesKey));

        if (_aesKey.SequenceEqual(decryptedAesKey)) Console.WriteLine("AES Key is same");
        // Decrypt the data with the decrypted AES key
        return Convert.ToBase64String(decryptedAesKey);
    }

 

Test

var publicKeyFilePath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, @"Certificate\Pem\public_key.pem");
var privateKeyFilePath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, @"Certificate\Pem\private.key");
var inputData = "1234Abcd 얼씨구리 절씨구리    지화자 蘭復a"u8;

using var aes = Aes.Create();
var key  = inputData;
using var rsa = RSA.Create();

var publicKey = rsa.ExportSubjectPublicKeyInfoPem();
var privateKey = rsa.ExportPkcs8PrivateKeyPem();

var encryptKey = EncryptionHelper.EncryptAesKeyDynamicKey(key.ToArray(), publicKey);
var decryptKey = EncryptionHelper.DecryptAesKeyDynamicKey(Convert.FromBase64String(encryptKey), privateKey);


Console.WriteLine(Encoding.UTF8.GetString(Convert.FromBase64String(decryptKey)));

 

 

관련영상

https://youtu.be/9Is1yKZZaJg

반응형