C# 是否可以使用WP7 AES128再现NIST/FIPS197结果?
各位程序员好!我希望允许我的软件用户以最方便、通用和平台独立的方式将信息从他们的Windows Phone设备安全地传输到两种不同的服务。最好使用微软已经提供的工具。出于这个原因,我研究了通过WindowsPhoneSDK7.1中的“System.Security.Cryptography”名称空间提供的AES托管类。然而,到目前为止,我甚至无法用这个类重现一个NIST示例。除其他外,我尝试了以下方法:C# 是否可以使用WP7 AES128再现NIST/FIPS197结果?,c#,windows-phone-7,encryption,aes,C#,Windows Phone 7,Encryption,Aes,各位程序员好!我希望允许我的软件用户以最方便、通用和平台独立的方式将信息从他们的Windows Phone设备安全地传输到两种不同的服务。最好使用微软已经提供的工具。出于这个原因,我研究了通过WindowsPhoneSDK7.1中的“System.Security.Cryptography”名称空间提供的AES托管类。然而,到目前为止,我甚至无法用这个类重现一个NIST示例。除其他外,我尝试了以下方法: /* http://csrc.nist.gov/publications/fips/fips
/* http://csrc.nist.gov/publications/fips/fips197/fips-197.pdf page 35 and 36 */
var passwordBytes = new byte[] { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f };
var unencryptedBytes = new byte[]{ 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff };
using (var aes = new AesManaged())
{
aes.BlockSize = 128; /* size in bits */
aes.KeySize = 128; /* size in bits */
aes.Key = passwordBytes;
using (var memoryStream = new MemoryStream())
{
using (var cryptoStream = new CryptoStream(memoryStream, aes.CreateEncryptor(), CryptoStreamMode.Write))
{
cryptoStream.Write(unencryptedBytes, 0, unencryptedBytes.Length);
cryptoStream.FlushFinalBlock();
var stream = memoryStream.ToArray();
/*
should be
69-c4-e0-d8-6a-7b-04-30-d8-cd-b7-80-70-b4-c5-5a = 128 bit
according to http://testprotect.com/appendix/AEScalc and fips-197.pdf
*/
var output = BitConverter.ToString(stream);
/*
86-DB-4D-44-72-C0-16-E6-80-B9-D2-B2-3C-6D-00-40-98-4C-59-76-CF-41-DF-4E-A6-46-BB-DE-4C-13-E6-12
256 bit?
*/
}
}
}
我看到了几个使用IV和Rfc2898DeriveBytes(eg)的代码示例(eg),但是默认情况下每个系统都理解的事实标准是什么?默认的“密钥填充”算法是什么,以及如何在windows phone上使用它(可能或?)。最后一点:我可以在Windows Phone上将默认模式(CBC根据)更改为任何其他模式吗?文档没有指出的是,它们对初始化向量使用全零。因此,将IV设置为全部为零的16个字节,它就可以工作了:
/* http://csrc.nist.gov/publications/fips/fips197/fips-197.pdf page 35 and 36 */
var passwordBytes = new byte[] { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f };
var unencryptedBytes = new byte[] { 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66,
0x77, 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff };
var initvectorBytes = new byte[] { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
using (var aes = new AesManaged())
{
aes.BlockSize = 128; /* size in bits */
aes.KeySize = 128; /* size in bits */
aes.Key = passwordBytes;
aes.IV = initvectorBytes;
using (var memoryStream = new MemoryStream())
{
using (var cryptoStream = new CryptoStream(
memoryStream, aes.CreateEncryptor(), CryptoStreamMode.Write))
{
cryptoStream.Write(unencryptedBytes, 0, unencryptedBytes.Length);
cryptoStream.FlushFinalBlock();
var stream = memoryStream.ToArray();
/* now you get:
69-c4-e0-d8-6a-7b-04-30-d8-cd-b7-80-70-b4-c5-5a = 128 bit
according to http://testprotect.com/appendix/AEScalc and fips-197.pdf
*/
var output = BitConverter.ToString(stream);
}
}
}
对于您的应用程序,您将希望使IV不是全零。由于AES是使用CBC模式(或ECB)实现的,因此您无法使用AES Managed更改模式。如果您尝试将其设置为任何其他值,则会出现异常。你可以随意改变填充物。我将把它保留为PKCS7(默认)。感谢您的快速响应。我几乎达到了预期的效果。然而,出于某种原因,输出长度为256位:“69-C4-E0-D8-6A-7B-04-30-D8-CD-B7-80-70-B4-C5-5A-9E-97-8E-6D-16-B0-86-57-0E-F7-94-EF-97-98-42-32”。这是由于使用“FlushFinalBlock”而不是“Flush”造成的。我猜与Flush()相反,填充魔法(PKCS7)是在FlushFinalBlock()调用中发生的,因此存在差异?我发现最有趣的是,AESSManaged似乎设置了一个随机(?)IV,以防不手动重写IV字节数组。非常不稳定的行为,不幸的是甚至没有提到。我询问了填充和模式,因为我找不到一种方法来设置WP7.1SDK中的这两个属性,尽管在其他平台上显然是可用的。将使我的代码正常工作并进行进一步测试,稍后再回来。我总是使用
FlushFinalBlock
。如果不需要额外的块,只需将填充更改为None
。如果要加密的数据大小等于块大小,并且填充不是None
,则会得到一个额外的数据块。额外的数据不应该引起关注,它只是填充。当您解密它时,它将被删除。他们的例子只是选择了不使用填充。让它在两个方向上工作(加密/解密)。非常感谢。