Giter Site home page Giter Site logo

duzun / cycle-crypt Goto Github PK

View Code? Open in Web Editor NEW
5.0 4.0 0.0 343 KB

Variable size symmetric key encryption algorithm. PHP & JavaScript implementation, small, portable and fast.

License: MIT License

JavaScript 45.61% PHP 37.79% Makefile 7.89% Shell 8.70%
symmetric-encryption encryption php nodejs browser salt cycle-crypt encryption-algorithm

cycle-crypt's Introduction

cycle-crypt codecov

Variable size symmetric key encryption algorithm.

PHP & JavaScript implementation, small, portable and fast.

The cipher-key is generated by cycling the input key with a variation of XorShift+ random number generator. The bigger the key-size, the longer the period.

Install

PHP

composer require duzun/cycle-crypt

JS

npm i -S cycle-crypt

Browser

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

Usage

Here is an example of encrypting on server and decrypting on client, salt auto-generated.

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'));
});

Browser:

// 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'

It is also possible to do the reverse: encrypt on client and decrypt on server.

You can also use your salt:

// 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);

On the JS end, message is an instance of Uint8Array with a custom .toString(encoding), where encoding is one of 'binary', 'hex', 'base64', 'utf8' or undefined (guess).

For older browsers you should use a DataView polyfill.

Encrypt in chunks

Here is an example of encrypting a big file in small chunks, thus avoid using lots of memory.

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)

You don't have to write the code to encrypt a file for yourself, cause there is a CLI for that:

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

Note: The Node.js CLI version is much faster than the PHP one.

CLI Usage

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 -

Warning!

If you deal with a security critical application, please consider using one of the NIST approved standard encryption algorithms like AES.

If you don't trust any encryption algorithm, here is a hint:

Choose two or more ciphers C1, C2 ... Cn from two or more vendors.

When ciphering the message M with C = M ^ C1 ^ C2 ^ ... ^ Cn, the secrecy of the cipher-text C is not worse than the best of Ci.

In other words, it can't hurt the secrecy when xoring more independent ciphers.

The theory behind this property is analysed and proven in my Masters Thesis:

The sum c = r1 ⊕ r2 ⊕ ... ⊕ rm, where c, ri ∊ 𝔹k (string of bits of length k), i=1,m, is a perfect secret if and only if there is at least one ri perfect secret and the operation ⊕ is a cryptographic safe operation.

To Do

The JS version uses Uint32Array and Uint8Array, which use little endian or big endian, depending on hardware. The current implementation has been tested in little endian HW only!

Have to implement the alternative to big endian too.

link

cycle-crypt's People

Contributors

dependabot[bot] avatar duzun avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar

cycle-crypt's Issues

[Question] About the design of cycle-crypt

I didn't understand this: "The cipher-key is generated by cycling the input key with a variation of XorShift+ random number generator."

/\ Does this means the input key is repeatedly XORed with an output of PRNG?

@duzun

If doesn't, could you please explain how the encryption is performed step by step?

[Question] About the chunk generation of modified XorShift+ PRNG used by cycle-crypt

I have a doubt about the modified XorShift+ used by cycle-crypt.

Let's suppose a I use a 1MiB key forcing cycle-crypt to process 1MiB chunks. Will the PRNG emit the output continuously or need to process the entire output block before emitting? I mean, can the modified PRNG emit chunks shorter than the internal state filled by the key without the need of discarding the rest of the sequence before next cycle?

Question: Is there a seed preprocessing in cycle-crypt?

Taking a look at speed measurements of SHAKE-256 (that can work as a stream cipher) I get the following timings:

Hashing a 1GB input:

$ time dd if=/dev/zero count=32768 bs=32768 | shake256sum -N 8
32768+0 records in
32768+0 records out
1073741824 bytes (1.1 GB, 1.0 GiB) copied, 4.85688 s, 221 MB/s
b4  -
real	0m4.859s
user	0m4.628s
sys	0m0.729s

Producing a 1GiB output:

time dd if=/dev/zero count=1 bs=1 | shake256sum -N 8589934592 > /dev/null 
1+0 records in
1+0 records out
1 byte copied, 2.9014e-05 s, 34.5 kB/s
real	0m6.540s
user	0m5.722s
sys	0m0.819s

Hashing a 1GiB input and producing a 1GiB output:

$ time dd if=/dev/zero count=32768 bs=32768 | shake256sum -N 8589934592 > /dev/null 
32768+0 records in
32768+0 records out
1073741824 bytes (1.1 GB, 1.0 GiB) copied, 4.65244 s, 231 MB/s
real	0m11.114s
user	0m9.980s
sys	0m1.614s

I can conclude that nearly half the CPU cycles per core was used to setup the internal state of SHAKE-256 and another half to generate the output.

Does the modified xorshift+ used by cycle-crypt needs to perform a "setup" with the seed in the internal state before emit the output like SHAKE-256 does? If yes, does the "setup" performed consumes nearly half the CPU cycles needed to transform a seed into a random output?

Resuming the question: Is the xorshift+ variant used by cycle-crypt Salsa20-like that processes the input (key+nonce+counter) directly?

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.