使用phpseclib复制C#RIjndael加密

时间:2017-06-22 07:54:04

标签: c# php encryption

我有这个C#类(下面)。接收方使用它来加密/解密我的消息。我正在尝试使用phpseclib加密/解密,我无法为接收器成功加密/解密。 使用phpseclib

的正确实现是什么
using System;
using System.IO;
using System.Security.Cryptography;

public class EncDec
{
    public static byte[] Encrypt(byte[] clearData, byte[] Key, byte[] IV)
    {
        MemoryStream ms = new MemoryStream();
        Rijndael alg = Rijndael.Create();

        alg.Key = Key;
        alg.IV = IV;

       CryptoStream cs = new CryptoStream(ms,
       alg.CreateEncryptor(), CryptoStreamMode.Write);

       cs.Write(clearData, 0, clearData.Length);
       cs.Close();

       byte[] encryptedData = ms.ToArray();

       return encryptedData;
   }

public static string Encrypt(string clearText, string Password)
{
    byte[] clearBytes =
      System.Text.Encoding.Unicode.GetBytes(clearText);


        new byte[] {0x49, 0x76, 0x61, 0x6e, 0x20, 0x4d, 
        0x65, 0x64, 0x76, 0x65, 0x64, 0x65, 0x76});

    byte[] encryptedData = Encrypt(clearBytes,
             pdb.GetBytes(32), pdb.GetBytes(16));

    return Convert.ToBase64String(encryptedData);
}

public static byte[] Encrypt(byte[] clearData, string Password)
{
    PasswordDeriveBytes pdb = new PasswordDeriveBytes(Password,
        new byte[] {0x49, 0x76, 0x61, 0x6e, 0x20, 0x4d, 
        0x65, 0x64, 0x76, 0x65, 0x64, 0x65, 0x76});

    return Encrypt(clearData, pdb.GetBytes(32), pdb.GetBytes(16));

}

public static void Encrypt(string fileIn,
            string fileOut, string Password)
{

    FileStream fsIn = new FileStream(fileIn,
        FileMode.Open, FileAccess.Read);
    FileStream fsOut = new FileStream(fileOut,
        FileMode.OpenOrCreate, FileAccess.Write);

    PasswordDeriveBytes pdb = new PasswordDeriveBytes(Password,
        new byte[] {0x49, 0x76, 0x61, 0x6e, 0x20, 0x4d, 
        0x65, 0x64, 0x76, 0x65, 0x64, 0x65, 0x76});

    Rijndael alg = Rijndael.Create();
    alg.Key = pdb.GetBytes(32);
    alg.IV = pdb.GetBytes(16);

    CryptoStream cs = new CryptoStream(fsOut,
        alg.CreateEncryptor(), CryptoStreamMode.Write);

    int bufferLen = 4096;
    byte[] buffer = new byte[bufferLen];
    int bytesRead;

    do
    {
        bytesRead = fsIn.Read(buffer, 0, bufferLen);
        cs.Write(buffer, 0, bytesRead);
    } while (bytesRead != 0);

    cs.Close();
    fsIn.Close();
}

public static byte[] Decrypt(byte[] cipherData,
                            byte[] Key, byte[] IV)
{
    MemoryStream ms = new MemoryStream();

    Rijndael alg = Rijndael.Create();

    alg.Key = Key;
    alg.IV = IV;

    CryptoStream cs = new CryptoStream(ms,
        alg.CreateDecryptor(), CryptoStreamMode.Write);

    cs.Write(cipherData, 0, cipherData.Length);
    cs.Close();

    byte[] decryptedData = ms.ToArray();
    return decryptedData;
}

public static string Decrypt(string cipherText, string Password)
{

    byte[] cipherBytes = Convert.FromBase64String(cipherText);

    PasswordDeriveBytes pdb = new PasswordDeriveBytes(Password,
        new byte[] {0x49, 0x76, 0x61, 0x6e, 0x20, 0x4d, 0x65, 
        0x64, 0x76, 0x65, 0x64, 0x65, 0x76});

    byte[] decryptedData = Decrypt(cipherBytes,
        pdb.GetBytes(32), pdb.GetBytes(16));

    return System.Text.Encoding.Unicode.GetString(decryptedData);
}

public static byte[] Decrypt(byte[] cipherData, string Password)
{        
    PasswordDeriveBytes pdb = new PasswordDeriveBytes(Password,
        new byte[] {0x49, 0x76, 0x61, 0x6e, 0x20, 0x4d, 
        0x65, 0x64, 0x76, 0x65, 0x64, 0x65, 0x76});

    return Decrypt(cipherData, pdb.GetBytes(32), pdb.GetBytes(16));
}

public static void Decrypt(string fileIn,
            string fileOut, string Password)
{
    FileStream fsIn = new FileStream(fileIn,
                FileMode.Open, FileAccess.Read);
    FileStream fsOut = new FileStream(fileOut,
                FileMode.OpenOrCreate, FileAccess.Write);

    PasswordDeriveBytes pdb = new PasswordDeriveBytes(Password,
        new byte[] {0x49, 0x76, 0x61, 0x6e, 0x20, 0x4d, 
        0x65, 0x64, 0x76, 0x65, 0x64, 0x65, 0x76});
       Rijndael alg = Rijndael.Create();

       alg.Key = pdb.GetBytes(32);
        alg.IV = pdb.GetBytes(16);

        CryptoStream cs = new CryptoStream(fsOut,
        alg.CreateDecryptor(), CryptoStreamMode.Write);

    int bufferLen = 4096;
    byte[] buffer = new byte[bufferLen];
    int bytesRead;

    do
    {
        bytesRead = fsIn.Read(buffer, 0, bufferLen);
        cs.Write(buffer, 0, bytesRead);

    } while (bytesRead != 0);

    cs.Close(); // this will also close the unrelying fsOut stream 
    fsIn.Close();
}
}

这是一个phpseclib的例子

 $rijndael = new \phpscelib\Crypt\Rijndael();
 $rijndael->setKey($encryption_password);

 $clear_text = $rijndael->decrypt($cipher_text);
 $cipher_text = $rijndael->encrypt($clear_text);

1 个答案:

答案 0 :(得分:1)

两个(或三个)关键问题:

  • 你没有在php端设置IV。
  • 您从c#代码中的密码派生密钥。对于您的PHP代码,您没有(您直接使用密码作为密钥)。
  • 使用c#中的Base64对密码字节进行编码。虽然我可能错了,但是php库似乎没有这样做。

安全问题:

  • 您正在使用PasswordDeriveBytes的固定盐。考虑生成一个加密随机盐并将其添加到您的密文。如果你想知道原因,这里有很多好的答案。
  • 直接使用明文密码/短语进行加密(如在PHP代码中)被认为是不安全的。加密密钥应该是随机的。密码哈希算法的输出没问题。