- android - RelativeLayout 背景可绘制重叠内容
- android - 如何链接 cpufeatures lib 以获取 native android 库?
- java - OnItemClickListener 不起作用,但 OnLongItemClickListener 在自定义 ListView 中起作用
- java - Android 文件转字符串
我正在编写一个简单的登录加密系统,但我遇到了一个小问题。C# 加密函数:
public static string EncryptString(string Message, string Passphrase)
{
byte[] Results;
System.Text.UTF8Encoding UTF8 = new System.Text.UTF8Encoding();
// Step 1. We hash the passphrase using MD5
// We use the MD5 hash generator as the result is a 128 bit byte array
// which is a valid length for the TripleDES encoder we use below
MD5CryptoServiceProvider HashProvider = new MD5CryptoServiceProvider();
byte[] TDESKey = HashProvider.ComputeHash(UTF8.GetBytes(Passphrase));
// Step 2. Create a new TripleDESCryptoServiceProvider object
TripleDESCryptoServiceProvider TDESAlgorithm = new TripleDESCryptoServiceProvider();
// Step 3. Setup the encoder
TDESAlgorithm.Key = TDESKey;
TDESAlgorithm.Mode = CipherMode.ECB;
TDESAlgorithm.Padding = PaddingMode.PKCS7;
// Step 4. Convert the input string to a byte[]
byte[] DataToEncrypt = UTF8.GetBytes(Message);
// Step 5. Attempt to encrypt the string
try
{
ICryptoTransform Encryptor = TDESAlgorithm.CreateEncryptor();
Results = Encryptor.TransformFinalBlock(DataToEncrypt, 0, DataToEncrypt.Length);
}
finally
{
// Clear the TripleDes and Hashprovider services of any sensitive information
TDESAlgorithm.Clear();
HashProvider.Clear();
}
// Step 6. Return the encrypted string as a base64 encoded string
return Convert.ToBase64String(Results);
}
EncryptString("test", "123456")
返回 "Yjaqhc7RFds="
。
php 中的相同代码:
<?php
$key = "123456";
function pkcs7_pad($text, $blocksize)
{
$pad = $blocksize - (strlen($text) % $blocksize);
return $text . str_repeat(chr($pad), $pad);
}
$input = pkcs7_pad("test", 16);
$key = md5(utf8_encode($key), true);
$td = mcrypt_module_open('tripledes', '', 'ecb', '');
$iv = mcrypt_create_iv (mcrypt_enc_get_iv_size($td), MCRYPT_RAND);
mcrypt_generic_init($td, $key, $iv);
$encrypted_data = mcrypt_generic($td, $input);
mcrypt_generic_deinit($td);
mcrypt_module_close($td);
echo base64_encode($encrypted_data);
?>
返回 “dybhiZYdKG8pNCgCFkbV6g==”
?我做错了什么?
最佳答案
您遇到此问题是因为 Triple DES 的 key 大小为 168 位(21 字节),但 MD5 生成的哈希值仅为 16 字节(128 位)长。
这意味着 key 必须扩展到 168 位,这样三重 DES 才能工作。事实证明,这种从 128 位到 168 位的推导在 C# 中的工作方式与在 PHP 中的工作方式不同,因此有效使用的 key 不同,从而导致不同的加密数据。
现在你有两个选择:
如果您使用支持 128 位 key 的密码,则可以避免与 key 大小差异相关的所有问题。这将需要对您的代码进行最少的更改。例如,您可以使用 Rijndael (AES)。
C#:将 TripleDESCryptoServiceProvider
更改为 RijndaelManaged
。
其他一切都可以保持几乎相同。 (Demo)
PHP:使用 MCRYPT_RIJNDAEL_128
而不是 tripledes (Demo) :
function encrypt_pkcs7($str, $key)
{
$key = md5(utf8_encode($key), true);
$block = mcrypt_get_block_size(MCRYPT_RIJNDAEL_128, MCRYPT_MODE_ECB);
$pad = $block - (strlen($str) % $block);
$str .= str_repeat(chr($pad), $pad);
$ciphertext = mcrypt_encrypt(MCRYPT_RIJNDAEL_128, $key, $str, MCRYPT_MODE_ECB);
return base64_encode($ciphertext);
}
echo encrypt_pkcs7('test', '123456');
请注意,AES 的有效 key 大小大于三重 DES。虽然 Triple DES 的 key 长度为 168 位,但它仅提供 112 位的安全性。如果我是你,我会选择这个选项。
如果您使用的 key 比 Triple DES 实际使用的 key 大,C# 和 PHP 似乎就如何将其减少到 168 位达成一致。您可以使用像 SHA-256 这样的散列函数来执行此操作,它会生成 256 位散列并将其修整为 192 位(24 字节):
C#:使用 SHA256CryptoServiceProvider
和 Array.Copy
获取 192 位 key ,并将其用于程序的其余部分: (Demo)
SHA256CryptoServiceProvider HashProvider = new SHA256CryptoServiceProvider();
byte[] temp = HashProvider.ComputeHash(UTF8.GetBytes(Passphrase));
byte[] key = new byte[24];
Array.Copy(temp, key, 24);
PHP:使用带有 SHA-256 的 hash()
和 substr()
获取 192 位 key
function encrypt_pkcs7($str, $key)
{
// derive 192-bit key using SHA-256
$key = substr(hash('sha256', $key, true), 0, 24);
$block = mcrypt_get_block_size(MCRYPT_3DES, MCRYPT_MODE_ECB);
$pad = $block - (strlen($str) % $block);
$str .= str_repeat(chr($pad), $pad);
$ciphertext = mcrypt_encrypt(MCRYPT_3DES, $key, $str, MCRYPT_MODE_ECB);
return base64_encode($ciphertext);
}
echo encrypt_pkcs7('test', '123456');
看起来我无法为 TripleDESCryptoServiceProvider
提供 168 位 key ,我不知道为什么。
考虑使用 SSL;即使它是自签名证书。它胜过重新发明轮子,这是一项在涉及密码学时特别危险的任务。
考虑使用 ECB 以外的操作模式(例如:CBC)。使用 ECB 会增加安全风险。阅读 Wikipedia article on block cipher modes of operation 。
除非您绝对需要明文密码(这种情况很少见),否则您应该散列您的密码。阅读 this article on securing passwords.
考虑使用适当的基于密码的 key 派生函数,例如 PBKDF2,而不是 MD5 或 SHA 系列等通用哈希函数。这将使破解 key 变得更加困难。有关详细信息,请阅读上一个要点中的文章。
关于c# - C# 和 PHP 上的三重 DES 加密产生不同的结果,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13402856/
我在 Chrome 上做了一些测试,requestAnimationFrame 产生了 61 fps 而 setTimeOut( callback, 0 ) 产生了 233 fps。 如果一个人想要超
当我调试代码时,我发现 GCC 和 Clang 都为 0.0/0.0 产生 nan,这是我所期望的,但 GCC 产生的 nan 将符号位设置为 1,而Clang 将其设置为 0(如果我没记错的话,与
Closed. This question does not meet Stack Overflow guidelines。它当前不接受答案。 想改善这个问题吗?更新问题,以便将其作为on-topic
我在 R Studio 中有一个时间序列。现在我想计算这个系列的log()。我尝试了以下方法: i <- (x-y) ii <- log(i) 但是我得到以下信息:Warning message: I
我有兴趣了解 JavaScript 的内部结构.我试图阅读 SpiderMonkey 的来源和 Rhino但是绕过我的头是相当复杂的。 我问的原因是:为什么像 (![]+[])[+!![]+[]] 生
我们在 Delphi 中使用标准 TWebbrowser 组件,该组件在内部使用 mshtml.dll。另外,我们使用注册表来确保页面使用新的渲染引擎( Web-Browser-Control-Spe
我必须实现一个序列化/反序列化类,并且我正在使用 System.Xml.Serialization 。我有一些IList类型属性并希望在 IList 中序列化解码属于具有特定区域性信息的列表的所有十进
我有一个 Java 应用程序,它读取包含 SQL 查询的 JSON 文件,并使用 JDBC 在数据库上触发它们。 现在我有 5 万个这样的文件,我需要生成 5 万个独立线程来读取每个文件并将它们上传到
我正在尝试将 TensorFlow 入门页面上的示例线性回归程序调整为二次回归。为此,我只是添加了另一个变量并更改了函数。然而,这似乎会导致 NaN 值。这是我的代码: import numpy as
申请后KernelPCA到我的数据并将其传递给分类器 ( SVC ) 我收到以下错误: ValueError: Input contains NaN, infinity or a value too
这背后的想法是,如果我的数据库中存在登录名(正确的用户名+密码),我将重定向到一个页面,并且在进行此身份验证后,他们可以将消息存储在文本文件中。代码非常简单尽管我不确定为什么会收到 IllegalSt
我有一个返回 log10 值的函数。在将它们转换为正常数字时,出现溢出错误。 OverflowError: (34, 'Numerical result out of range') 我检查了日志值,
nosetests 抛出一个 ImportError,尽管我认为这是一个正确配置的 virtualenv。 ==============================================
我是这个网站的新手,所以如果我做错了什么,我提前道歉。当我尝试使用 kivy-garden 的 ScrollLabel 时,它给了我一个错误。基本上我正在尝试创建一个控制台日志,并且我需要能够在文本框
任何人都对 MDSJ 有任何经验?以下输入仅产生 NaN 结果,我不明白为什么。文档非常稀少。 import mdsj.Data; import mdsj.MDSJ; public class MDS
我有一个非常简单的 scala jcuda 程序,它添加了一个非常大的数组。一切都编译和运行得很好,直到我想从我的设备复制超过 4 个字节到主机。当我尝试复制超过 4 个字节时,我收到 CUDA_ER
我正在使用 Hero 组件在两个页面之间创建动画。Hero 组件用于包装一个 Image 小部件(没问题)和一个 Container 小部件(有问题)。 抛出以下溢出错误: ══╡ EXCEPTIO
我无法理解页面 https://developer.mozilla.org/en/JavaScript/Reference/Operators/Special/void 中的这一段: This ope
当在 Angular 中使用不立即触发事件的异步管道时(http 请求或任何有延迟的可观察对象),第一个值为 null为什么会这样?如何避免这种情况? 第一个变化: SimpleChange {
如果一个导入的库生成了一个会 panic 的 goroutine 怎么办?在这种情况下,开发人员无法阻止程序退出。 就像在这段代码中一样,使用延迟恢复调用一个错误的库没有帮助,因为该库正在生成一个 p
我是一名优秀的程序员,十分优秀!