diff options
author | Jason A. Donenfeld <Jason@zx2c4.com> | 2020-02-12 17:23:57 +0100 |
---|---|---|
committer | Jason A. Donenfeld <Jason@zx2c4.com> | 2020-02-12 17:28:17 +0100 |
commit | bb69a91669bb985b4b8d7a42127e5c08c0a29ae6 (patch) | |
tree | 691d039c479fed93f529b7579c54221df2d24858 | |
download | chacha20.sh-master.tar.gz chacha20.sh-master.tar.bz2 chacha20.sh-master.zip |
Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com>
-rw-r--r-- | COPYING | 19 | ||||
-rw-r--r-- | README.md | 23 | ||||
-rwxr-xr-x | chacha20.sh | 102 |
3 files changed, 144 insertions, 0 deletions
@@ -0,0 +1,19 @@ +Copyright (C) 2020 Jason A. Donenfeld <Jason@zx2c4.com>. All Rights Reserved. + +Permission is hereby granted, free of charge, to any person obtaining a copy of +this software and associated documentation files (the "Software"), to deal in +the Software without restriction, including without limitation the rights to +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies +of the Software, and to permit persons to whom the Software is furnished to do +so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/README.md b/README.md new file mode 100644 index 0000000..5f77444 --- /dev/null +++ b/README.md @@ -0,0 +1,23 @@ +## chacha20.sh +#### by zx2c4 + +You probably shouldn't use this for anything. + +### Usage + +``` +chacha20 [HEX KEY] [NUMERIC NONCE] [HEX CIPHERTEXT] +``` + +### Example + +``` +local ciphertext="d42efa92e92968b7542cf7a42db750b5c5b29d175e0aca37bf60aed298e9fa596762e6430c7780823361a3ffc1a08f56bcec654388a5ff516430ee34b75c2868c352d2ac782aa610b8b24c804f99b236948f66cba191ed06426dc1ae5593dd939e88347f98ebbe61f9a90fd9c487d5efcc718c0ecead02cfa261dfb1fe3bdcc058b571a183c9b4af9d5412cdea06d64ee5270cc3bba80a8175c3c9d4353e539faa20c068392c96395381da070f44a5470eb3870d1bc1e54135125896698a1aa39d3dd4b18e1f9687dad319e2b13a1974a0009f4dbccb0ce9ec10df2a88dc3051465653986a2614055481550b3c85dd33811129824635e1db597b" +local key="a92075897e378548a3fb7be830a7e36ea6c17117c16c9bc2def0a719eccec653" +local nonce=5394271251748129296 + +chacha20 "$key" "$nonce" "$ciphertext" +``` + + + diff --git a/chacha20.sh b/chacha20.sh new file mode 100755 index 0000000..5952f8f --- /dev/null +++ b/chacha20.sh @@ -0,0 +1,102 @@ +#!/bin/bash +# SPDX-License-Identifier: MIT +# Copyright (C) 2020 Jason A. Donenfeld <Jason@zx2c4.com>. All Rights Reserved. + + +rol() { + echo $(( (($1 << $2) | ($1 >> (32 - $2))) & 0xffffffff )) +} + +quarter_round() { + local -n x=$1; shift + x[$1]=$(( (x[$1] + x[$2]) & 0xffffffff )) + x[$4]=$(rol $(( (x[$4] ^ x[$1]) & 0xffffffff )) 16) + x[$3]=$(( (x[$3] + x[$4]) & 0xffffffff )) + x[$2]=$(rol $(( (x[$2] ^ x[$3]) & 0xffffffff )) 12) + x[$1]=$(( (x[$1] + x[$2]) & 0xffffffff )) + x[$4]=$(rol $(( (x[$4] ^ x[$1]) & 0xffffffff )) 8) + x[$3]=$(( (x[$3] + x[$4]) & 0xffffffff )) + x[$2]=$(rol $(( (x[$2] ^ x[$3]) & 0xffffffff )) 7) +} + +c() { + echo $(( ($1 << 2) + $2 )) +} + +double_round() { + quarter_round $1 $(c 0 0) $(c 1 0) $(c 2 0) $(c 3 0) + quarter_round $1 $(c 0 1) $(c 1 1) $(c 2 1) $(c 3 1) + quarter_round $1 $(c 0 2) $(c 1 2) $(c 2 2) $(c 3 2) + quarter_round $1 $(c 0 3) $(c 1 3) $(c 2 3) $(c 3 3) + quarter_round $1 $(c 0 0) $(c 1 1) $(c 2 2) $(c 3 3) + quarter_round $1 $(c 0 1) $(c 1 2) $(c 2 3) $(c 3 0) + quarter_round $1 $(c 0 2) $(c 1 3) $(c 2 0) $(c 3 1) + quarter_round $1 $(c 0 3) $(c 1 0) $(c 2 1) $(c 3 2) +} + +twenty_rounds() { + double_round $1 + double_round $1 + double_round $1 + double_round $1 + double_round $1 + double_round $1 + double_round $1 + double_round $1 + double_round $1 + double_round $1 +} + +le() { + echo $(( ($1 >> 0) & 0xff)) $(( ($1 >> 8) & 0xff)) $(( ($1 >> 16) & 0xff)) $(( ($1 >> 24) & 0xff)) +} + +one_block() { + local -n state=$1 + local -n stream=$2 + local block=( ${state[@]} ) + twenty_rounds block + for (( i=0; i < 16; i++ )); do + stream+=( $(le $(( (state[$i] + block[$i]) & 0xffffffff )) ) ) + done + state[12]=$(( (state[12] + 1) & 0xffffffff )) + (( state[12] != 0 )) || state[13]=$(( (state[13] + 1) & 0xffffffff )) +} + +dehex() { + echo $(( (0x${1:0:2} << 0) | (0x${1:2:2} << 8) | (0x${1:4:2} << 16) | (0x${1:6:2} << 24) )) +} + +# Usage: chacha20 [HEX KEY] [NUMERIC NONCE] [HEX CIPHERTEXT] +chacha20() { + local cstate=( + 1634760805 857760878 2036477234 1797285236 + $(dehex ${1:0:8}) $(dehex ${1:8:8}) $(dehex ${1:16:8}) $(dehex ${1:24:8}) + $(dehex ${1:32:8}) $(dehex ${1:40:8}) $(dehex ${1:48:8}) $(dehex ${1:56:8}) + 0 0 $(( $2 & 0xffffffff )) $(( ($2 >> 32) & 0xffffffff )) + ) + local ciphertext="$3" + local n=0 + while true; do + [[ -n ${ciphertext:$n} ]] || { echo; return 0; } + local cstream=() + one_block cstate cstream + for (( i=0; i < 64; i++ )); do + [[ -n ${ciphertext:$n} ]] || { echo; return 0; } + printf '%02x' $(( cstream[$i] ^ 0x${ciphertext:$n:2} )) + (( n+=2 )) + done + done +} + +test_vector() { + local ciphertext="d42efa92e92968b7542cf7a42db750b5c5b29d175e0aca37bf60aed298e9fa596762e6430c7780823361a3ffc1a08f56bcec654388a5ff516430ee34b75c2868c352d2ac782aa610b8b24c804f99b236948f66cba191ed06426dc1ae5593dd939e88347f98ebbe61f9a90fd9c487d5efcc718c0ecead02cfa261dfb1fe3bdcc058b571a183c9b4af9d5412cdea06d64ee5270cc3bba80a8175c3c9d4353e539faa20c068392c96395381da070f44a5470eb3870d1bc1e54135125896698a1aa39d3dd4b18e1f9687dad319e2b13a1974a0009f4dbccb0ce9ec10df2a88dc3051465653986a2614055481550b3c85dd33811129824635e1db597b" + local plaintext="646cda7fd4a92a5e22ae8d67dbeefdd0448017b2e387ad5715cb8864c0f1493dfabea89f12c3575670a5c56bf1abd5de77926a5603f5210db6c4cc62443fb1c1614190b2d5b8f357fbc26b2558c8452072296f9db5814d2bb2899e9153971cd93d79dc14ae017375f0cad5ab625c7a7d3ffe227deee2cb7655ec06dd414718621d57d0d6b60f4bfc7919f4d63786181f980d9e152db69a8a8c80222f82c4c736fafa07bdc22ae2ea93c8b29033f2ee4b1bf4379213bbe2cee303cf0794ab9ac9ff83693ada2cd0473d6c1a606847b93652dd16ef6cbf54117262ce8c9d90a02506923e127e1a1de5a271ce1c4c6a7cdc3de36e489db3647d7840" + local key="a92075897e378548a3fb7be830a7e36ea6c17117c16c9bc2def0a719eccec653" + local nonce=5394271251748129296 + + [[ $(chacha20 "$key" "$nonce" "$ciphertext") == "$plaintext" ]] && echo pass || echo fail + [[ $(chacha20 "$key" "$nonce" "$plaintext") == "$ciphertext" ]] && echo pass || echo fail +} + +test_vector |