2012-11-08 21 views
5

KeyとIVを使用してRSC2-cbcアルゴリズムを使用して、C#で暗号化と復号化のログインが既に実装されています。今度はnode.jsに実装するつもりです。暗号化と復号化のために次のコードを書いています。私が直面している問題は、node.jsで暗号化された文字列(chiper)または復号化された文字列がC#のencryptrd文字列と一致しないことです。Node.JS RC2-CBC暗号化と復号化の暗号がC#と一致しません

既存のC#コード

byte[] arrbIV = Encoding.ASCII.GetBytes("dleftaba"); 
byte[] arrbKey = Encoding.ASCII.GetBytes(Key); 
byte[] arrbData = Encoding.ASCII.GetBytes(sData); //Text to be encryptrd 

RC2 oEncryptor = new RC2CryptoServiceProvider(); 

oEncryptor.Mode = CipherMode.CBC; 
oEncryptor.Key = arrbKey; 
oEncryptor.IV = arrbIV; 

// Create memory stream to store encrypted string 
MemoryStream oMemoryStream = new MemoryStream(); 
CryptoStream oCryptoStream = new CryptoStream(oMemoryStream, oEncryptor.CreateEncryptor(),  
CryptoStreamMode.Write); 

// Peform the encryption 
oCryptoStream.Write(arrbData, 0, arrbData.Length); 
// We have written all the data in the stream and now we can apply padding 
oCryptoStream.Close(); 
string sRetVal = Convert.ToBase64String(oMemoryStream.ToArray()); 

等価/訳Node.jsのコード

var crypto = require('crypto') 

var SECRET_KEY = "435353553" 

var IV = "dleftaba" 

var ENCODING = 'base64' 

var text = "My Text" 


Encryption 

var cipher = crypto.createCipheriv('rc2-cbc',key, iv) 
var cryptedPassword = cipher.update(text, 'utf-8', 'base64') 
cryptedPassword+= cipher.final('base64') 

Decryption 

var decipher = crypto.createDecipheriv('rc2-cbc', SECRET_KEY, IV) 
var decryptedPassword = decipher.update(cryptedPassword, 'base64','utf-8') 
decryptedPassword += decipher.final('utf-8') 

Please suggest what is going wrong over here. Why node. js is not resulting into the identical chiper like C#. 
+0

こんにちは、これに答えましたか?私は同じ問題に直面しています。 – govin

+0

私は答えは分かりませんが、[NodeはOpenSSLを暗号化に使用しています](http://nodejs.org/api/crypto.html#crypto_crypto)ので、より詳しく見ることができます。 –

+0

C#コードで生成された暗号化された結果を期待できますか? – skieter

答えて

0

...ここにあなたが使用しているのと同じアルゴリズムですしていないが、私のreference implementation in C# ...私が置かれているコメントノードの実装はどうすればいいのでしょうか...そしてそれは一致します...

当時の私の目標は、.Net側をノード側のデフォルトと互換性を保つことでした...

関連:

using System; 
using System.Collections.Generic; 
using System.IO; 
using System.Linq; 
using System.Security.Cryptography; 
using System.Text; 
using System.Threading.Tasks; 

namespace T1.CoreUtils 
{ 
    public static class CryptoUtility 
    { 
     /* Wanting to stay compatible with NodeJS 
     * https://stackoverflow.com/questions/18502375/aes256-encryption-decryption-in-both-nodejs-and-c-sharp-net/ 
     * https://stackoverflow.com/questions/12261540/decrypting-aes256-encrypted-data-in-net-from-node-js-how-to-obtain-iv-and-key 
     * https://stackoverflow.com/questions/8008253/c-sharp-version-of-openssl-evp-bytestokey-method 
     */ 

     /* EncrypteDefault - as NodeJS 
     * var cipher = crypto.createCipher('aes-256-cbc', 'passphrase'); 
     * var encrypted = cipher.update("test", 'utf8', 'base64') + cipher.final('base64'); 
     */ 
     public static string EncryptDefault(string input, string passphrase = null) 
     { 
      byte[] key, iv; 
      PassphraseToDefaultKeyAndIV(RawBytesFromString(passphrase), null, 1, out key, out iv); 

      return Convert.ToBase64String(EncryptBytes(Encoding.UTF8.GetBytes(input), key, iv)); 
     } 

     /* DecryptDefault - as NodeJS 
     * var decipher = crypto.createDecipher('aes-256-cbc', 'passphrase'); 
     * var plain = decipher.update(encrypted, 'base64', 'utf8') + decipher.final('utf8'); 
     */ 
     public static string DecryptDefault(string inputBase64, string passphrase = null) 
     { 
      byte[] key, iv; 
      PassphraseToDefaultKeyAndIV(RawBytesFromString(passphrase), null, 1, out key, out iv); 

      return Encoding.UTF8.GetString(DecryptBytes(Convert.FromBase64String(inputBase64), key, iv)); 
     } 

     public static string Encrypt(string input, string passphrase = null) 
     { 
      byte[] key, iv; 
      PassphraseToSCryptKeyAndIV(passphrase, out key, out iv); 

      return Convert.ToBase64String(EncryptBytes(Encoding.UTF8.GetBytes(input), key, iv)); 
     } 

     public static string Decrypt(string inputBase64, string passphrase = null) 
     { 
      byte[] key, iv; 
      PassphraseToSCryptKeyAndIV(passphrase, out key, out iv); 

      return Encoding.UTF8.GetString(DecryptBytes(Convert.FromBase64String(inputBase64), key, iv)); 

     } 

     static byte[] RawBytesFromString(string input) 
     { 
      var ret = new List<Byte>(); 

      foreach (char x in input) 
      { 
       var c = (byte)((ulong)x & 0xFF); 
       ret.Add(c); 
      } 

      return ret.ToArray(); 
     } 

     public static void PassphraseToSCryptKeyAndIV(string passphrase, out byte[] key, out byte[] iv) 
     { 
      var hashList = HashUtility.HashSCrypt(Encoding.UTF8.GetBytes(passphrase)).ToList(); 
      key = new byte[32]; 
      iv = new byte[16]; 
      hashList.CopyTo(0, key, 0, 32); 
      hashList.CopyTo(32, iv, 0, 16); 
     } 

     public static void PassphraseToDefaultKeyAndIV(byte[] data, byte[] salt, int count, out byte[] key, out byte[] iv) 
     { 
      List<byte> hashList = new List<byte>(); 
      byte[] currentHash = new byte[0]; 

      int preHashLength = data.Length + ((salt != null) ? salt.Length : 0); 
      byte[] preHash = new byte[preHashLength]; 

      System.Buffer.BlockCopy(data, 0, preHash, 0, data.Length); 
      if (salt != null) 
       System.Buffer.BlockCopy(salt, 0, preHash, data.Length, salt.Length); 

      MD5 hash = MD5.Create(); 
      currentHash = hash.ComputeHash(preHash); 

      for (int i = 1; i < count; i++) 
      { 
       currentHash = hash.ComputeHash(currentHash); 
      } 

      hashList.AddRange(currentHash); 

      while (hashList.Count < 48) // for 32-byte key and 16-byte iv 
      { 
       preHashLength = currentHash.Length + data.Length + ((salt != null) ? salt.Length : 0); 
       preHash = new byte[preHashLength]; 

       System.Buffer.BlockCopy(currentHash, 0, preHash, 0, currentHash.Length); 
       System.Buffer.BlockCopy(data, 0, preHash, currentHash.Length, data.Length); 
       if (salt != null) 
        System.Buffer.BlockCopy(salt, 0, preHash, currentHash.Length + data.Length, salt.Length); 

       currentHash = hash.ComputeHash(preHash); 

       for (int i = 1; i < count; i++) 
       { 
        currentHash = hash.ComputeHash(currentHash); 
       } 

       hashList.AddRange(currentHash); 
      } 
      hash.Clear(); 
      key = new byte[32]; 
      iv = new byte[16]; 
      hashList.CopyTo(0, key, 0, 32); 
      hashList.CopyTo(32, iv, 0, 16); 
     } 

     public static byte[] EncryptBytes(byte[] input, byte[] Key, byte[] IV) 
     { 
      // Check arguments. 
      if (input == null || input.Length <= 0) 
       return new byte[0]; //nothing to encode 
      if (Key == null || Key.Length <= 0) 
       throw new ArgumentNullException("Key"); 
      if (IV == null || IV.Length <= 0) 
       throw new ArgumentNullException("Key"); 

      // Create an RijndaelManaged object 
      // with the specified key and IV. 
      using (RijndaelManaged cipher = new RijndaelManaged()) 
      { 
       cipher.Key = Key; 
       cipher.IV = IV; 
       cipher.Mode = CipherMode.CBC; 
       cipher.Padding = PaddingMode.PKCS7; 

       // Create a decrytor to perform the stream transform. 
       ICryptoTransform encryptor = cipher.CreateEncryptor(cipher.Key, cipher.IV); 

       // Create the streams used for encryption. 
       using (MemoryStream outputStream = new MemoryStream()) 
       { 
        using (CryptoStream encryptStream = new CryptoStream(outputStream, encryptor, CryptoStreamMode.Write)) 
        { 
         encryptStream.Write(input, 0, input.Length); 
         encryptStream.FlushFinalBlock(); 
         outputStream.Seek(0, 0); 
         return outputStream.ToArray(); 
        } 
       } 
      } 

     } 

     public static byte[] DecryptBytes(byte[] cipherText, byte[] Key, byte[] IV) 
     { 
      // Check arguments. 
      if (cipherText == null || cipherText.Length <= 0) 
       throw new ArgumentNullException("cipherText"); 
      if (Key == null || Key.Length <= 0) 
       throw new ArgumentNullException("Key"); 
      if (IV == null || IV.Length <= 0) 
       throw new ArgumentNullException("Key"); 

      // Create an RijndaelManaged object 
      // with the specified key and IV. 
      using (var cipher = new RijndaelManaged()) 
      { 
       cipher.Key = Key; 
       cipher.IV = IV; 
       cipher.Mode = CipherMode.CBC; 
       cipher.Padding = PaddingMode.PKCS7; 

       // Create a decrytor to perform the stream transform. 
       ICryptoTransform decryptor = cipher.CreateDecryptor(cipher.Key, cipher.IV); 

       // Create the streams used for decryption. 
       using (var inputStream = new MemoryStream(cipherText)) 
       { 
        using (var outputStream = new MemoryStream()) 
        { 
         using (CryptoStream decryptedStream = new CryptoStream(inputStream, decryptor, CryptoStreamMode.Read)) 
         { 
          var buffer = new byte[1024]; 
          decryptedStream.Flush(); 
          var read = decryptedStream.Read(buffer, 0, buffer.Length); 
          while (read > 0) 
          { 
           outputStream.Write(buffer, 0, read); 
           decryptedStream.Flush(); 
           read = decryptedStream.Read(buffer, 0, buffer.Length); 
          } 
          outputStream.Seek(0, 0); 
          return outputStream.ToArray(); 
         } 
        } 
       } 
      } 
     } 
    } 
}

のNode.js

var crypto = require('crypto'); 

module.exports = { 
    encrypt: encryptValue, 
    decrypt: decryptValue 
} 

function encryptValue(input, passphrase) { 
    var cipher = crypto.createCipher('aes-256-cbc', passphrase); 
    var encrypted = cipher.update(input, 'utf8', 'base64') + cipher.final('base64'); 
    return encrypted; 
} 

function decryptValue(inputBase64, passphrase) { 
    var decipher = crypto.createDecipher('aes-256-cbc', passphrase); 
    var plain = decipher.update(inputBase64, 'base64', 'utf8') + decipher.final('utf8'); 
    return plain; 
}

私の.Netコード参照HashUtilityは厳密には必要ではありません。私は完全なnode.js実装を利用可能なscryptで利用していません。