duzun/cycle-crypt

可变大小的对称密钥加密算法

安装: 17

依赖项: 0

建议者: 0

安全: 0

星标: 5

关注者: 4

分支: 0

开放性问题: 0

语言:JavaScript

1.3.0 2022-12-10 12:46 UTC

README

可变大小的 对称 密钥加密算法。

PHP & JavaScript实现,小巧、便携且快速。

密钥生成通过将输入密钥与XorShift+随机数生成器的变体进行循环。密钥大小越大,周期越长。

安装

PHP

composer require duzun/cycle-crypt

JS

npm i -S cycle-crypt

浏览器

<script src="https://unpkg.com/cycle-crypt"></script>

用法

以下是一个在服务器端加密并在客户端解密的示例,盐自动生成。

PHP

// index.php

use function duzun\cycleCrypt;

$key = '*** *** ***'; // any length
$message = 'Lorem Ipsum is simply dummy text of the printing industry...';
$ciphered = cycleCrypt($key, $message, true);

// send $ciphered to the client
echo base64_encode($ciphered);

Express.js

// index.js
const cycleCrypt = require('cycle-crypt');
//   or
// import cycleCrypt from 'cycle-crypt';

const key = '*** *** ***'; // any length

// ...

app.get('/', function (req, res) {
    // const salt = cycleCrypt.randomBytes(17);
    let message = 'Lorem Ipsum is simply dummy text of the printing industry...';
    let ciphered = cycleCrypt(key, message, true);

    res.send(Buffer.from(ciphered).toString('base64'));
});

浏览器

// site.js
const key = '*** *** ***'; // must be the same key used for encrypting

let message = await fetch('/')
.then((r) => r.text())
.then(atob)
.then((ciphered) => cycleCrypt(key, ciphered, false));

console.log(message.toString('utf8')); // 'hex' | 'base64'

也可以做相反的操作:在客户端加密并在服务器端解密。

您也可以使用自己的盐

// index.php

// ...

$salt = random_bytes(17); // any length
$ciphered = cycleCrypt($key, $message, $salt);

// Have to send the salt to the client too
echo json_encode([
    'salt' => base64_encode($salt),
    'ciphered' => base64_encode($ciphered)
]);
// site.js

// fetch ciphered & salt from server and base64 decode ...
let message = cycleCrypt(key, ciphered, salt);

在JS端,message 是一个具有自定义 .toString(encoding)Uint8Array 实例,其中 encoding 是 'binary'、'hex'、'base64'、'utf8' 或 undefined(猜测)之一。

对于旧浏览器,您应使用 DataView polyfill。

分块加密

以下是一个将大文件分小块加密的示例,从而避免使用大量内存。

use duzun\CycleCrypt;

$cc = new CycleCrypt($key/*, $salt=true*/);
$salt = $cc->getSalt(); // required for decryption
$chunkSize = $cc->getKeyByteSize();

$in = fopen('/path/to/file', '+r');
$out = fopen('/path/to/encrypted_file', '+w');
while(!feof($in)) {
    $chunk = fread($in, $chunkSize);
    fwrite($out, $cc($chunk));
}
fclose($in);
fclose($out);

file_put_contents('/path/to/encrypted_file.salt', $salt)

您不需要编写加密文件的代码,因为有一个CLI工具可以做到这一点

Node.js

npm install -g cycle-crypt

cycle-crypt -k '**** ****' -s 'the salt' -i /path/to/file -o /path/to/encrypted_file

PHP

composer global require duzun/cycle-crypt

cycry.php -k '**** ****' -s 'the salt' -i /path/to/file -o /path/to/encrypted_file

注意:Node.js CLI版本比PHP版本快得多。

CLI用法

cycle-crypt -k <key> [-s <salt> | -si <salt_in> | -so <salt_out>] [-sr <salt_rounds>] [-i <file_in>] [-o <file_out>]
cycle-crypt -h|--help

-h, --help      Show this help
-k, --key       The encryption key. Could be hex if starts with '0x'.
-s, --salt      Random bytes to be used as salt. Could be hex if starts with '0x'.
                Can contain the salt-rounds as "0x<salt_in_hex>x<salt_rounds>".
-si, --salt-in  Filename or - from where to read the salt.
-so, --salt-out Filename or - where to output the generated salt.
-sr, --salt-rounds Number of rounds of initial state generated from salt + key
-i, --in        Input file to encrypt or - for STDIN
-o, --out       Output file or - for STDOUT

You can not combine -s and -si, use just one of them.    

-i and -o default to -

警告!

如果您处理的是安全关键型应用程序,请考虑使用NIST批准的标准加密算法之一,如AES

如果您不信任任何加密算法,这里有一个提示

从两个或多个供应商中选择两个或多个加密算法 C1C2 ... Cn

当使用 C = M ^ C1 ^ C2 ^ ... ^ Cn 对消息 M 进行加密时,密文 C 的保密性不会比最佳 Ci 差。

换句话说,当对更多的独立加密算法进行异或操作时,这不会损害保密性。

这个特性的理论已经在我的硕士论文中进行了分析和证明

总和 c = r1 ⊕ r2 ⊕ ... ⊕ rm,其中 c、ri ∈ 𝔹k(长度为k的比特串),i=1,m,是一个 完美保密 如果且仅如果至少有一个 ri 是完美的保密,并且操作 ⊕ 是一个 加密安全 操作。

待办事项

JS版本使用Uint32Array和Uint8Array,它们使用小端或大端,取决于硬件。当前实现仅在little endian硬件上进行了测试!

必须实现大端端的替代方案。

链接