Skip to content

Instantly share code, notes, and snippets.

@ysc3839
Last active March 9, 2019 13:11
Show Gist options
  • Save ysc3839/187c3bf6f27bcfc1fccd783bc9b717fc to your computer and use it in GitHub Desktop.
Save ysc3839/187c3bf6f27bcfc1fccd783bc9b717fc to your computer and use it in GitHub Desktop.
// https://github.com/B-Con/crypto-algorithms/blob/master/sha1.c
const SHA1_BLOCK_SIZE = 20
class sha1_ctx
{
constructor()
{
data = array(64, 0);
datalen = 0;
bitlen = 0;
state = [
0x67452301,
0xEFCDAB89,
0x98BADCFE,
0x10325476,
0xc3d2e1f0
];
}
function ROTLEFT(a, b) { return ((a << b) | (a >>> (32 - b))); }
function _transform()
{
local a, b, c, d, e, i, j, t, m = array(80, 0);
for (i = 0, j = 0; i < 16; ++i, j += 4)
m[i] = (data[j] << 24) + (data[j + 1] << 16) + (data[j + 2] << 8) + (data[j + 3]);
for ( ; i < 80; ++i) {
m[i] = (m[i - 3] ^ m[i - 8] ^ m[i - 14] ^ m[i - 16]) & 0xFFFFFFFF;
m[i] = ((m[i] << 1) | (m[i] >>> 31)) & 0xFFFFFFFF;
}
a = state[0];
b = state[1];
c = state[2];
d = state[3];
e = state[4];
for (i = 0; i < 20; ++i) {
t = (ROTLEFT(a, 5) + ((b & c) ^ (~b & d)) + e + k[0] + m[i]) & 0xFFFFFFFF;
e = d;
d = c;
c = ROTLEFT(b, 30);
b = a;
a = t;
}
for ( ; i < 40; ++i) {
t = (ROTLEFT(a, 5) + (b ^ c ^ d) + e + k[1] + m[i]) & 0xFFFFFFFF;
e = d;
d = c;
c = ROTLEFT(b, 30);
b = a;
a = t;
}
for ( ; i < 60; ++i) {
t = (ROTLEFT(a, 5) + ((b & c) ^ (b & d) ^ (c & d)) + e + k[2] + m[i]) & 0xFFFFFFFF;
e = d;
d = c;
c = ROTLEFT(b, 30);
b = a;
a = t;
}
for ( ; i < 80; ++i) {
t = (ROTLEFT(a, 5) + (b ^ c ^ d) + e + k[3] + m[i]) & 0xFFFFFFFF;
e = d;
d = c;
c = ROTLEFT(b, 30);
b = a;
a = t;
}
state[0] += a & 0xFFFFFFFF;
state[1] += b & 0xFFFFFFFF;
state[2] += c & 0xFFFFFFFF;
state[3] += d & 0xFFFFFFFF;
state[4] += e & 0xFFFFFFFF;
}
function update(_data)
{
for (local i = 0; i < _data.len(); ++i) {
data[datalen] = _data[i];
datalen++;
if (datalen == 64) {
_transform();
bitlen += 512;
datalen = 0;
}
}
}
function final()
{
local i = datalen;
// Pad whatever data is left in the buffer.
if (datalen < 56) {
data[i++] = 0x80;
while (i < 56)
data[i++] = 0x00;
}
else {
data[i++] = 0x80;
while (i < 64)
data[i++] = 0x00;
_transform();
//memset(ctx->data, 0, 56);
for (local j = 0; j < 56; ++j)
data[j] = 0;
}
// Append to the padding the total message's length in bits and transform.
bitlen += datalen * 8;
data[63] = bitlen;
data[62] = bitlen >>> 8;
data[61] = bitlen >>> 16;
data[60] = bitlen >>> 24;
if (_intsize_ >= 8) {
data[59] = bitlen >>> 32;
data[58] = bitlen >>> 40;
data[57] = bitlen >>> 48;
data[56] = bitlen >>> 56;
} else {
data[59] = 0;
data[58] = 0;
data[57] = 0;
data[56] = 0;
}
_transform();
local hash = array(SHA1_BLOCK_SIZE);
// Since this implementation uses little endian byte ordering and MD uses big endian,
// reverse all the bytes when copying the final state to the output hash.
for (i = 0; i < 4; ++i) {
hash[i] = (state[0] >>> (24 - i * 8)) & 0x000000ff;
hash[i + 4] = (state[1] >>> (24 - i * 8)) & 0x000000ff;
hash[i + 8] = (state[2] >>> (24 - i * 8)) & 0x000000ff;
hash[i + 12] = (state[3] >>> (24 - i * 8)) & 0x000000ff;
hash[i + 16] = (state[4] >>> (24 - i * 8)) & 0x000000ff;
}
return hash;
}
data = null;
datalen = null;
bitlen = null;
state = null;
static k = [
0x5a827999,
0x6ed9eba1,
0x8f1bbcdc,
0xca62c1d6,
];
};
function sha1(data)
{
local ctx = sha1_ctx();
ctx.update(data);
return ctx.final();
}
dofile("sha1.nut");
local data = "abc";
print(format("sha1(\"%s\")=", data));
local hash = sha1(data);
for (local i = 0; i < hash.len(); ++i)
print(format("%02x", hash[i]));
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment