2

I am trying to verify a signed hash made by the Node.js Crypto API using UWP's CryptographicEngine. Because the Verify method kept returning false, I am now comparing both signature methods. When I sign a simple string using both systems, I get different results.

Here is the Crypto JS code:

//Generate signer and hasher
var signature = crypto.createSign('RSA-SHA256');

var hasher = crypto.createHash("SHA256");    
hasher.update('mydata');

//Generate hash from data
hashresult = hasher.digest('base64');

signature.update(hashresult);

//Read private key
var inputkey = fs.readFileSync('private.pem');

//Sign Data
var result = signature.sign(inputkey, 'base64');

And here is the CryptographicEngine code:

IBuffer buffer = CryptographicBuffer.ConvertStringToBinary("mydata", BinaryStringEncoding.Utf8);

HashAlgorithmProvider hashAlgorithm = HashAlgorithmProvider.OpenAlgorithm(HashAlgorithmNames.Sha256);

IBuffer hashBuffer = hashAlgorithm.HashData(buffer);

var basehash = CryptographicBuffer.EncodeToBase64String(hashBuffer);

Debug.WriteLine("HASHED RESULT");
Debug.WriteLine(basehash);

//ENCRYPT SIGNATURE using GetPrivateKey to get base64 key without headers
string privatekey = await GetPrivateKey();
//Convert key to IBuffer
IBuffer privatekeybuf = CryptographicBuffer.DecodeFromBase64String(privatekey);

AsymmetricKeyAlgorithmProvider provider = AsymmetricKeyAlgorithmProvider.OpenAlgorithm(AsymmetricAlgorithmNames.RsaSignPkcs1Sha256);

CryptographicKey encryptKey = provider.ImportKeyPair(privatekeybuf, CryptographicPrivateKeyBlobType.Pkcs1RsaPrivateKey);

var encryptedresult = CryptographicEngine.Sign(encryptKey, hashbuffer);

string resultencrypted = CryptographicBuffer.EncodeToBase64String(encryptedresult);

Debug.WriteLine("ENCRYPTED RESULT");
Debug.WriteLine(resultencrypted);

I have verified that the two hashes that are created in both JS and UWP are equal. The result of both signing methods however, is not. How can these be different? It seems the encoding is equal. I have tried both Sign and SignHashedData in UWP and have also tried various other encodings.

Any ideas?

Artjom B.
  • 61,146
  • 24
  • 125
  • 222
WJM
  • 1,137
  • 1
  • 15
  • 30
  • This http://stackoverflow.com/questions/13419201/why-are-the-rsa-sha256-signatures-i-generate-with-openssl-and-java-different has some ideas about how to look at the generated output. The node crypto api is a wrapper around openssl but it's not clear from the docs exactly how they produce this signature. – pvg Jan 12 '16 at 21:00

1 Answers1

1

Both Node.js's Sign class and CryptographicEngine.Sign expect the unhashed data. You don't need to hash your data additionally. You should remove the double hashing in Node.js and C#.

RSA encryption and signature generation uses padding in order to provide any meaningful security. There are different types of padding which are equivalent, but some are randomized. If either Node.js or UWP uses a randomized padding, then you can't simply compare the signature results. The only way to check if your implementations are compatible, would be to sign some data in one end and verify in the other. Then repeat that in the other direction.

Artjom B.
  • 61,146
  • 24
  • 125
  • 222
  • Double hashing seems to happen in both cases. And while it could be different the padding is almost certainly not randomized. – pvg Jan 12 '16 at 21:08
  • @pvg PKCS#1 v1.5 padding type 2 is randomized, I still misinterpreted the documentation. You're right, `CryptographicEngine.Sign` expects unhashed data. – Artjom B. Jan 12 '16 at 21:14
  • Ah I thought you meant the padding method itself. Not really exposed in the node API although most likely pkcs1 – pvg Jan 12 '16 at 21:27