当前位置: 首页 > 面试题库 >

如何从AES加密字符串中添加/删除PKCS7填充?

袁桐
2023-03-14
问题内容

我正在尝试使用128位AES加密(ECB)加密/解密字符串。我想知道的是如何向其中添加/删除PKCS7填充。看起来Mcrypt扩展可以处理加密/解密,但是必须手动添加/删除填充。

有任何想法吗?


问题答案:

让我们来看看。RFC 5652(加密消息语法)中描述了PKCS#7。

填充方案本身在第6.3节中给出。内容加密过程。它的本质是说:根据需要追加许多字节以填充给定的块大小(但至少一个字节),并且每个字节都应将填充长度作为值。

因此,查看最后一个解密的字节,我们知道要剥离多少字节。(也可以检查它们是否具有相同的值。)

我现在可以给您一对PHP函数来执行此操作,但是我的PHP有点生锈。因此,您可以自己执行此操作(然后随意编辑我的答案以将其添加到其中),或者查看用户为mcrypt文档提供的注释 -其中很多都是关于填充的,并提供了PKCS#7填充的实现。

因此,让我们详细了解一下第一个音符

<?php

function encrypt($str, $key)
 {
     $block = mcrypt_get_block_size('des', 'ecb');

这将获得所使用算法的块大小。在您的情况下,我想使用aesrijndael_128代替des(我没有对其进行测试)。(相反,您可以在16这里简单地使用AES,而不用调用该函数。)

     $pad = $block - (strlen($str) % $block);

这将计算填充大小。strlen($str)是数据的长度(以字节为单位),% $block以余数为模$block,即最后一块中的数据字节数。$block - ...因此,给出了填充最后一个块所需的字节数(现在是1和之间的数字$block,含)。

     $str .= str_repeat(chr($pad), $pad);

str_repeat]产生一个字符串,该字符串由相同字符串的重复组成,此处是由$pad$pad倍给出的字符]的重复,即长度为的字符串$pad,填充有$pad
$str .= ...将此填充字符串附加到原始数据。

     return mcrypt_encrypt(MCRYPT_DES, $key, $str, MCRYPT_MODE_ECB);

这是加密本身。使用MCRYPT_RIJNDAEL_128代替MCRYPT_DES

 }

现在另一个方向:

 function decrypt($str, $key)
 {   
     $str = mcrypt_decrypt(MCRYPT_DES, $key, $str, MCRYPT_MODE_ECB);

解密。(您当然会如上所述更改算法)。$ str现在是解密的字符串,包括填充。

     $block = mcrypt_get_block_size('des', 'ecb');

这也是块大小。(往上看。)

     $pad = ord($str[($len = strlen($str)) - 1]);

这看起来有些奇怪。最好分多个步骤编写:

    $len = strlen($str);
    $pad = ord($str[$len-1]);

$len现在是填充字符串的长度,并且$str[$len - 1]是该字符串的最后一个字符。ord将此转换为数字。因此$pad,这是我们之前用作填充的填充值的数字,这是填充长度。

     return substr($str, 0, strlen($str) - $pad);

因此,现在我们$pad从字符串中切除了最后一个字节。(而不是strlen($str)我们也可以$len在这里写:substr($str, 0,$len - $pad)。)。

 }

?>

请注意,除了使用之外substr($str, $len - $pad),还可以编写substr($str, -$pad),因为substrPHP中的函数对负操作数/自变量进行了特殊处理,以从字符串末尾开始计数。(我不知道这比首先获取长度和手动计算索引要高还是低。)

如前所述,并在rossum的注释中指出,与其简单地像这里一样剥离填充,不如检查它是否正确,即查看substr($str, $len - $pad),并检查其所有字节是否正确chr($pad)。这只是对损坏的轻微检查(尽管如果使用链接模式而不是ECB,此检查会更有效,并且不能代替真实的MAC)。

(并且仍然告诉您的客户,他们应该考虑更改为比ECB更安全的模式。)



 类似资料:
  • 我一直在到处寻找一些示例代码,介绍如何使用Bouncy Castle框架用标题中的加密加密一个简单的字符串。 此代码将在Windows Universal项目上运行。我以前尝试使用内置API进行加密,但在服务器上解密失败。 服务器使用 但失败的原因是: 填充无效,无法删除。 初始化向量的长度必须与块大小相同 服务器上的长度为128。我怎么能强迫它是等长的?

  • 要求: 我有一个Ruby on rails应用程序,我需要执行以下操作。 以下字符串应使用3DES算法和工作密钥加密。ABJGTU9的加密值将是vV51P0OGXt0= 工作密钥为 A5157A0D77B24AEA868AD73288366826 以下文献中提到的3DES算法使用以下步骤进行数据加密: i.使用CBC密码模式和PKCS7填充的密钥的左侧部分加密数据。ii.使用CBC密码模式和无填充

  • 所以我有一个AES-256-ecb base64字符串,我用在线工具解码了它。然而,我更喜欢命令行,所以我尝试使用命令行来解码它。 这是我尝试过的,但我得到了严重的解密错误 是加密的base64文本 -aes-256-ecb是加密密码 而366a74cb3c959de17d61db30591c39d1是关键 结果应该是另一个base64字符串:

  • 我面临AES填充问题。我使用的是Alcides Soares FIlho(用C#生成128位字符串)中建议的代码。请注意,我的加密侧码是。。。 另外,我传递给明文的值是“Z4YAZZSQ 001F295E2589AWAN HANS”。加密正在进行。但解密失败了。 解密侧码 我应该能拿回“Z4YAZZSQ 001F295E2589AWAN HANS” 但出现以下错误“填充无效,无法删除”请建议解决方

  • 问题内容: 如何使用AES加密整个字符串。我下面的代码仅加密最多识别的第一个空格:(。我该如何解决这个问题?谢谢 编辑 OMG,我不愿意相信这一点,但我怎么可能会这样想:(因为我的扫描仪接下来是nextLine而不是nextLine,所以让我整日感到困扰是多么令人困扰,直到现在我才真正想到要进行检查。问题已解决:)谢谢大家 问题答案: 我没有看到任何你的代码错误,除了尝试打印任意使用。尝试以下尺寸