简体   繁体   中英

Why does signing algorithm in C# give different result than the one in Javascript

This is the algorithm for signing the data in C# using a private key from a certificate that is used from both me and the client in order to define an unique key to identify the user:

X509Certificate2 keyStore = new X509Certificate2(AppDomain.CurrentDomain.BaseDirectory + "Certifikatat\\" + certPath, certPass, X509KeyStorageFlags.Exportable);
RSA privateKey = keyStore.GetRSAPrivateKey();
byte[] iicSignature = privateKey.SignData(Encoding.ASCII.GetBytes("K31418036C|2022-5-16 13:30:41|406|st271ir481|al492py609|zz463gy579|340"), HashAlgorithmName.SHA256, RSASignaturePadding.Pkcs1);
byte[] iic = ((HashAlgorithm)CryptoConfig,CreateFromName("MD5")).ComputeHash(iicSignature);

I then pass the private key to my Javascript using Bouncy Castle:

X509Certificate2 keyStore = new X509Certificate2(AppDomain.CurrentDomain.BaseDirectory + "Certifikatat\\" + certPath, certPass, X509KeyStorageFlags.Exportable);
RSA privateKey = keyStore.GetRSAPrivateKey();
var eky = DotNetUtilities.GetRsaKeyPair(privateKey);
Pkcs8Generator pkcs8Gen = new Pkcs8Generator(eky.Private);
Org.BouncyCastle.Utilities.IO.Pem.PemObject pkcs8 = pkcs8Gen.Generate();
PemWriter pemWriter = new PemWriter(new StringWriter());
pemWriter.WriteObject(pkcs8);
pemWriter.Writer.Flush();
return pemWriter.Writer.ToString();

This one is the algorithm used in Javascript:

 window.crypto.subtle.importKey( "pkcs8", pemToArrayBuffer(pkcs8Pem), { name: "RSASSA-PKCS1-v1_5", hash: { name: "SHA-256" }, }, false, ["sign"] ) .then(function(privateKey) { console.log(privateKey); // Sign: RSA with SHA256 and PKCS#1 v1.5 padding window.crypto.subtle.sign({ name: "RSASSA-PKCS1-v1_5", }, privateKey, new TextEncoder().encode("K31418036C|2022-5-16 13:30:41|406|st271ir481|al492py609|zz463gy579|340") ) .then(function(signature) { var iic = md5(signature); console.log(ab2b64(signature)); }) .catch(function(err) { console.error(err); }); }) .catch(function(err) { console.error(err); }); function ab2b64(arrayBuffer) { return window.btoa(String.fromCharCode.apply(null, new Uint8Array(arrayBuffer))); } function removeLines(str) { str = str.replace("\r", ""); return str.replace("\n", ""); } function base64ToArrayBuffer(b64) { var byteString = atob(b64); var byteArray = new Uint8Array(byteString.length); for (var i = 0; i < byteString.length; i++) { byteArray[i] = byteString.charCodeAt(i); } return byteArray; } function pemToArrayBuffer(pem) { var b64Lines = removeLines(pem); var b64Prefix = b64Lines.replace('-----BEGIN PRIVATE KEY-----', ''); var b64Final = b64Prefix.replace('-----END PRIVATE KEY-----', ''); return base64ToArrayBuffer(b64Final); }

The signatures returned are different for some reason. I need them to be the same or else it's all pointless because the client won't be authenticated.

The results are as follow:

C#:
57CF663ACBEDE6305309682BA7261412

Javascript:
c099d176dcd95c59d748d6066dcd462e

I had to convert my signature to base64 and then encode it with atob() after that i needed this md5 library to hash the data and then use .toUpperCase() to reproduce the correct result.

The complete code looks like this:

md5(atob(ab2b64(signature))).toUpperCase();

Now i get the same result from both C# and JS.

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