【发布时间】:2016-09-02 15:17:44
【问题描述】:
前段时间,我实现了一个 C# Web API 来提供信息。
此信息已加密,可供其他 C# 或经典 ASP 网站使用。
这就是我使用 EncryptRijndael 和 DecryptRijndael 方法进行加密/解密的方式。
using System;
using System.Text;
namespace Encryption_Test
{
using System.IO;
using System.Security.Cryptography;
using System.Text.RegularExpressions;
using System.Windows.Forms;
class RijndaelManagedEncryption
{
//http://www.codeproject.com/Tips/704372/How-to-use-Rijndael-ManagedEncryption-with-Csharp
#region Rijndael Encryption
/// <summary>
/// Encrypt the given text and give the byte array back as a BASE64 string
/// </summary>
/// <param name="text" />The text to encrypt
/// <param name="salt" />The pasword salt
/// <returns>The encrypted text</returns>
public static string EncryptRijndael(string text, string salt, string inputKey)
{
if (string.IsNullOrEmpty(text))
throw new ArgumentNullException("text");
var aesAlg = NewRijndaelManaged(salt, inputKey);
var blockSize = aesAlg.BlockSize;
var strK = System.Text.Encoding.ASCII.GetString(aesAlg.Key);
string s = strK;
var encryptor = aesAlg.CreateEncryptor(aesAlg.Key, aesAlg.IV);
var msEncrypt = new MemoryStream();
using (var csEncrypt = new CryptoStream(msEncrypt, encryptor, CryptoStreamMode.Write))
using (var swEncrypt = new StreamWriter(csEncrypt))
{
swEncrypt.Write(text);
}
return Convert.ToBase64String(msEncrypt.ToArray());
}
#endregion
#region Rijndael Dycryption
/// <summary>
/// Checks if a string is base64 encoded
/// </summary>
/// <param name="base64String" />The base64 encoded string
/// <returns>
public static bool IsBase64String(string base64String)
{
base64String = base64String.Trim();
return (base64String.Length%4 == 0) &&
Regex.IsMatch(base64String, @"^[a-zA-Z0-9\+/]*={0,3}$", RegexOptions.None);
}
/// <summary>
/// Decrypts the given text
/// </summary>
/// <param name="cipherText" />The encrypted BASE64 text
/// <param name="salt" />
/// <param name="inputKey"></param>
/// The pasword salt
/// <returns>De gedecrypte text</returns>
public static string DecryptRijndael(string cipherText, string salt, string inputKey)
{
if (string.IsNullOrEmpty(cipherText))
throw new ArgumentNullException("cipherText");
if (!IsBase64String(cipherText))
throw new Exception("The cipherText input parameter is not base64 encoded");
string text;
var aesAlg = NewRijndaelManaged(salt, inputKey);
var decryptor = aesAlg.CreateDecryptor(aesAlg.Key, aesAlg.IV);
var cipher = Convert.FromBase64String(cipherText);
using (var msDecrypt = new MemoryStream(cipher))
{
using (var csDecrypt = new CryptoStream(msDecrypt, decryptor, CryptoStreamMode.Read))
{
using (var srDecrypt = new StreamReader(csDecrypt))
{
text = srDecrypt.ReadToEnd();
}
}
}
return text;
}
#endregion
#region NewRijndaelManaged
/// <summary>
/// Create a new RijndaelManaged class and initialize it
/// </summary>
/// <param name="salt" />
/// <param name="inputKey"></param>
/// The pasword salt
/// <returns>
private static RijndaelManaged NewRijndaelManaged(string salt, string inputKey)
{
if (salt == null) throw new ArgumentNullException("salt");
var saltBytes = Encoding.ASCII.GetBytes(salt);
var key = new Rfc2898DeriveBytes(inputKey, saltBytes);
var aesAlg = new RijndaelManaged();
aesAlg.Key = key.GetBytes(aesAlg.KeySize / 8); //256 / 8 = 32
aesAlg.IV = key.GetBytes(aesAlg.BlockSize / 8); //128 / 8 = 16
//string k = System.Text.Encoding.Default.GetString(aesAlg.Key);
//string i = System.Text.Encoding.Default.GetString(aesAlg.IV);
//string l = k + i;
#region testPHP
///*
// So it would seem the week point in the chain for PHP is the Rfc2898DeriveBytes
// */
//aesAlg.Key = Encoding.UTF8.GetBytes(inputKey);
//aesAlg.IV = Encoding.UTF8.GetBytes(salt);
//k = System.Text.Encoding.Default.GetString(aesAlg.Key);
//i = System.Text.Encoding.Default.GetString(aesAlg.IV);
//l = k + i;
#endregion testPHP
return aesAlg;
}
#endregion
}
}
您可以在接近结尾时看到注释掉了,我只是通过将提供的参数转换为 byte[] 来设置 Key 和 IV。这对 PHP 来说似乎没问题,但我不想省略 Rfc2898DeriveBytes。
它工作得很好,消费网站能够解密信息。
现在这是我的(以及其他人的问题,但我想帮忙),一个 PHP 站点现在需要使用我的 Web API。他们似乎做不到。他们认为这是由于 IV 的创建方式造成的。
现在这让我怀疑
- 他们不能胜任这项工作
- 我的实施使他们无法做到。
现在我对 PHP 知之甚少,但通常可以按照它的代码块的流程进行操作。 如果有人能首先告诉我是否应该可以使用 PHP 实现目标,我将不胜感激,如果可以,也许可以提供一些关于如何做到这一点的指示。
注意 - 这是利用 Rfc2898DeriveBytes,我认为这是问题的症结所在,并将此问题与其他类似问题区分开来。
一个例子
- 要加密的字符串:
Co-operation is the key to success! - 盐:
This_is_the_password_salt - 输入键:
This_is_the_input_key - 加密字符串:
pLgIEjhNGDMfI0IynoAdbey3NKbOJzgUzYAlU14OWOpuZy7/lr7HRtFhiRKfjbZz
【问题讨论】:
-
不,这不是重复的。您指的是没有使用 Rfc2898DeriveBytes。看起来这件作品尤其是问题所在。
-
@RiggsFolly - 请重新打开
-
您没有提供关于您如何实际加密数据的足够信息,因此几乎不可能提供帮助。你也不是有问题的人,所以我们看不到其他人试图解密你的数据。所以这个问题有点无法回答
-
我现在包含了代码而不是链接。
-
告诉你什么!您使用 C# 代码加密已知字符串。发布您开始使用的字符串和生成的加密字符串,这里有人可能会编写一些 PHP 来解密它。这至少会证明这是可能的。然后,您可以返回给您的用户并告诉他们如何操作。 这听起来像计划吗
标签: c# php encryption rijndaelmanaged