为什么这个密文总是以相同的字符开头

Why does this ciphertext always start with the same characters?

本文关键字:字符 开头 密文 为什么      更新时间:2023-09-26

我开始玩CryptoJS,我注意到了一些奇怪的事情:密文总是以相同的字符串开头。这是执行加密的代码(我知道Math.random在加密方面不安全,这只是一些快速而肮脏的东西)。

function Controller($scope) {
    $scope.Text = "";
    $scope.CipherText = "";
    $scope.Key = Math.random().toString();
    $scope.Encrypt = function ($event) {
        $scope.CipherText = CryptoJS.AES.encrypt($scope.Text, $scope.Key).toString();
    }
}

使用HTML:

<div ng-controller="Controller">
    <div>Your key is: "{{Key}}".</div>
    <div>
        <textarea ng-change="Encrypt()" ng-model="Text" maxlength="140">{{Text}}</textarea>
        <br />
        <span>{{Text.length}} of 140</span>
    </div>
    <div>
        <textarea ng-model="CipherText" maxlength="216">{{CipherText}}</textarea>
        <br />
        <span>{{CipherText.length}} of 216</span>
    </div>
</div>

运行几次后,我注意到base64密文总是以相同的几个字符开头。对于密钥0.5640227501280606:

a: U2FsdGVkX19kMKXVbnJHKbEkrwctAm2YbOTnPmtGRCg=
b: U2FsdGVkX18+0sG2DQzVgHwxH2cvrSqaDIxOOkUt5YU=
c: U2FsdGVkX19xGQdT6OUhbyyg1zfgqpGnWvF5Ibqkuqc=

我已经用不同的密钥和不同长度的明文尝试过了。密文总是以U2FsdGVkX1开头。这是怎么回事?CryptoJS是否在这里存储了一些内部信息?或者在某些情况下,这对AES来说是正常的吗?

解码字符串,似乎是

U2FsdGVkX19

解码为

Salted_

FIDDLE

所以它只是CryptoJS添加的一个字符串,作为盐

添加到密文的初始字符串是"Salted__"(没有引号,末尾有两个下划线),表明接下来的八个字节是salt值,后面是密文。

这可能会与OpenSSL保持二进制兼容性,如果使用密码而不是密钥,OpenSSL也会这样做。然后使用EVP_BytesToKey函数导出密钥。这是OpenSSL的专有协议,不是添加盐或从密码派生密钥的标准化方法。