mirror of
https://github.com/vlang/v.git
synced 2023-08-10 21:13:21 +03:00
crypto md5
This commit is contained in:
parent
8c516bec4f
commit
9c586e7e92
143
vlib/crypto/md5/md5.v
Normal file
143
vlib/crypto/md5/md5.v
Normal file
@ -0,0 +1,143 @@
|
||||
// Copyright (c) 2019 Alexander Medvednikov. All rights reserved.
|
||||
// Use of this source code is governed by an MIT license
|
||||
// that can be found in the LICENSE file.
|
||||
|
||||
// Package md5 implements the MD5 hash algorithm as defined in RFC 1321.
|
||||
|
||||
// MD5 is cryptographically broken and should not be used for secure
|
||||
// applications.
|
||||
|
||||
// Adapted from: https://github.com/golang/go/blob/master/src/crypto/md5
|
||||
|
||||
module md5
|
||||
|
||||
import math
|
||||
import encoding.binary
|
||||
|
||||
const (
|
||||
// The size of an MD5 checksum in bytes.
|
||||
Size = 16
|
||||
// The blocksize of MD5 in bytes.
|
||||
BlockSize = 64
|
||||
)
|
||||
|
||||
const (
|
||||
Init0 = 0x67452301
|
||||
Init1 = 0xEFCDAB89
|
||||
Init2 = 0x98BADCFE
|
||||
Init3 = 0x10325476
|
||||
)
|
||||
|
||||
// Digest represents the partial evaluation of a checksum.
|
||||
struct Digest {
|
||||
mut:
|
||||
s []u32
|
||||
x []byte
|
||||
nx int
|
||||
len u64
|
||||
}
|
||||
|
||||
fn (d mut Digest) reset() {
|
||||
d.s = [u32(0); 4]
|
||||
d.x = [byte(0); BlockSize]
|
||||
d.s[0] = u32(Init0)
|
||||
d.s[1] = u32(Init1)
|
||||
d.s[2] = u32(Init2)
|
||||
d.s[3] = u32(Init3)
|
||||
d.nx = 0
|
||||
d.len = u64(0)
|
||||
}
|
||||
|
||||
// New returns a new hash.Hash computing the MD5 checksum.
|
||||
pub fn new() *Digest {
|
||||
mut d := &Digest{}
|
||||
d.reset()
|
||||
return d
|
||||
}
|
||||
|
||||
pub fn (d mut Digest) write(p []byte) ?int {
|
||||
nn := p.len
|
||||
d.len += u64(nn)
|
||||
if d.nx > 0 {
|
||||
n := int(math.min(f64(d.x.len), f64(p.len)))
|
||||
for i:=0; i<n; i++ {
|
||||
d.x.set(i+d.nx, p[i])
|
||||
}
|
||||
d.nx += n
|
||||
if d.nx == BlockSize {
|
||||
block_generic(d, d.x)
|
||||
d.nx = 0
|
||||
}
|
||||
if n >= p.len {
|
||||
p = []byte
|
||||
} else {
|
||||
p = p.right(n)
|
||||
}
|
||||
}
|
||||
if p.len >= BlockSize {
|
||||
n := p.len &~ (BlockSize - 1)
|
||||
block_generic(d, p.left(n))
|
||||
if n >= p.len {
|
||||
p = []byte
|
||||
} else {
|
||||
p = p.right(n)
|
||||
}
|
||||
}
|
||||
if p.len > 0 {
|
||||
d.nx = int(math.min(f64(d.x.len), f64(p.len)))
|
||||
for i:=0; i<d.nx; i++ {
|
||||
d.x.set(i, p[i])
|
||||
}
|
||||
}
|
||||
return nn
|
||||
}
|
||||
|
||||
pub fn (d &Digest) sum(b_in mut []byte) []byte {
|
||||
// Make a copy of d so that caller can keep writing and summing.
|
||||
mut d0 := *d
|
||||
hash := d0.checksum()
|
||||
for b in hash {
|
||||
b_in << b
|
||||
}
|
||||
return *b_in
|
||||
}
|
||||
|
||||
pub fn (d mut Digest) checksum() []byte {
|
||||
// Append 0x80 to the end of the message and then append zeros
|
||||
// until the length is a multiple of 56 bytes. Finally append
|
||||
// 8 bytes representing the message length in bits.
|
||||
//
|
||||
// 1 byte end marker :: 0-63 padding bytes :: 8 byte length
|
||||
// tmp := [1 + 63 + 8]byte{0x80}
|
||||
mut tmp := [byte(0); 1 + 63 + 8]
|
||||
tmp[0] = 0x80
|
||||
pad := (55 - int(d.len)) % 64 // calculate number of padding bytes
|
||||
binary.little_endian_put_u64(tmp.right(1+pad), u64(d.len<<u64(3))) // append length in bits
|
||||
d.write(tmp.left(1+pad+8))
|
||||
|
||||
// The previous write ensures that a whole number of
|
||||
// blocks (i.e. a multiple of 64 bytes) have been hashed.
|
||||
if d.nx != 0 {
|
||||
panic('d.nx != 0')
|
||||
}
|
||||
|
||||
digest := [byte(0); Size]
|
||||
|
||||
binary.little_endian_put_u32(digest, d.s[0])
|
||||
binary.little_endian_put_u32(digest.right(4), d.s[1])
|
||||
binary.little_endian_put_u32(digest.right(8), d.s[2])
|
||||
binary.little_endian_put_u32(digest.right(12), d.s[3])
|
||||
return digest
|
||||
}
|
||||
|
||||
// Sum returns the MD5 checksum of the data.
|
||||
// pub fn Sum(data []byte) [Size]byte {
|
||||
pub fn sum(data []byte) []byte {
|
||||
mut d := new()
|
||||
d.write(data)
|
||||
return d.checksum()
|
||||
}
|
||||
|
||||
pub fn (d &Digest) size() int { return Size }
|
||||
|
||||
pub fn (d &Digest) block_size() int { return BlockSize }
|
9
vlib/crypto/md5/md5_test.v
Normal file
9
vlib/crypto/md5/md5_test.v
Normal file
@ -0,0 +1,9 @@
|
||||
// Copyright (c) 2019 Alexander Medvednikov. All rights reserved.
|
||||
// Use of this source code is governed by an MIT license
|
||||
// that can be found in the LICENSE file.
|
||||
|
||||
import crypto.md5
|
||||
|
||||
fn test_crypto_md5() {
|
||||
assert md5.sum('this is a md5 checksum.'.bytes()).hex() == '6FB421FF99036547655984DA12973431'
|
||||
}
|
129
vlib/crypto/md5/md5block_generic.v
Normal file
129
vlib/crypto/md5/md5block_generic.v
Normal file
@ -0,0 +1,129 @@
|
||||
// Copyright (c) 2019 Alexander Medvednikov. All rights reserved.
|
||||
// Use of this source code is governed by an MIT license
|
||||
// that can be found in the LICENSE file.
|
||||
|
||||
// This is a generic implementation with no arch optimizations
|
||||
|
||||
module md5
|
||||
|
||||
import math.bits
|
||||
import encoding.binary
|
||||
|
||||
fn block_generic(dig &Digest, p []byte) {
|
||||
// load state
|
||||
mut a := dig.s[0]
|
||||
mut b := dig.s[1]
|
||||
mut c := dig.s[2]
|
||||
mut d := dig.s[3]
|
||||
for i := 0; i <= p.len-BlockSize; i += BlockSize {
|
||||
mut q := p.right(i)
|
||||
q = q.left(BlockSize)
|
||||
// save current state
|
||||
aa := a
|
||||
bb := b
|
||||
cc := c
|
||||
dd := d
|
||||
|
||||
// load input block
|
||||
x0 := binary.little_endian_u32(q.right(4*0x0))
|
||||
x1 := binary.little_endian_u32(q.right(4*0x1))
|
||||
x2 := binary.little_endian_u32(q.right(4*0x2))
|
||||
x3 := binary.little_endian_u32(q.right(4*0x3))
|
||||
x4 := binary.little_endian_u32(q.right(4*0x4))
|
||||
x5 := binary.little_endian_u32(q.right(4*0x5))
|
||||
x6 := binary.little_endian_u32(q.right(4*0x6))
|
||||
x7 := binary.little_endian_u32(q.right(4*0x7))
|
||||
x8 := binary.little_endian_u32(q.right(4*0x8))
|
||||
x9 := binary.little_endian_u32(q.right(4*0x9))
|
||||
xa := binary.little_endian_u32(q.right(4*0xa))
|
||||
xb := binary.little_endian_u32(q.right(4*0xb))
|
||||
xc := binary.little_endian_u32(q.right(4*0xc))
|
||||
xd := binary.little_endian_u32(q.right(4*0xd))
|
||||
xe := binary.little_endian_u32(q.right(4*0xe))
|
||||
xf := binary.little_endian_u32(q.right(4*0xf))
|
||||
|
||||
// round 1
|
||||
a = b + bits.rotate_left_32((((c^d)&b)^d)+a+x0+u32(0xd76aa478), 7)
|
||||
d = a + bits.rotate_left_32((((b^c)&a)^c)+d+x1+u32(0xe8c7b756), 12)
|
||||
c = d + bits.rotate_left_32((((a^b)&d)^b)+c+x2+u32(0x242070db), 17)
|
||||
b = c + bits.rotate_left_32((((d^a)&c)^a)+b+x3+u32(0xc1bdceee), 22)
|
||||
a = b + bits.rotate_left_32((((c^d)&b)^d)+a+x4+u32(0xf57c0faf), 7)
|
||||
d = a + bits.rotate_left_32((((b^c)&a)^c)+d+x5+u32(0x4787c62a), 12)
|
||||
c = d + bits.rotate_left_32((((a^b)&d)^b)+c+x6+u32(0xa8304613), 17)
|
||||
b = c + bits.rotate_left_32((((d^a)&c)^a)+b+x7+u32(0xfd469501), 22)
|
||||
a = b + bits.rotate_left_32((((c^d)&b)^d)+a+x8+u32(0x698098d8), 7)
|
||||
d = a + bits.rotate_left_32((((b^c)&a)^c)+d+x9+u32(0x8b44f7af), 12)
|
||||
c = d + bits.rotate_left_32((((a^b)&d)^b)+c+xa+u32(0xffff5bb1), 17)
|
||||
b = c + bits.rotate_left_32((((d^a)&c)^a)+b+xb+u32(0x895cd7be), 22)
|
||||
a = b + bits.rotate_left_32((((c^d)&b)^d)+a+xc+u32(0x6b901122), 7)
|
||||
d = a + bits.rotate_left_32((((b^c)&a)^c)+d+xd+u32(0xfd987193), 12)
|
||||
c = d + bits.rotate_left_32((((a^b)&d)^b)+c+xe+u32(0xa679438e), 17)
|
||||
b = c + bits.rotate_left_32((((d^a)&c)^a)+b+xf+u32(0x49b40821), 22)
|
||||
|
||||
// round 2
|
||||
a = b + bits.rotate_left_32((((b^c)&d)^c)+a+x1+u32(0xf61e2562), 5)
|
||||
d = a + bits.rotate_left_32((((a^b)&c)^b)+d+x6+u32(0xc040b340), 9)
|
||||
c = d + bits.rotate_left_32((((d^a)&b)^a)+c+xb+u32(0x265e5a51), 14)
|
||||
b = c + bits.rotate_left_32((((c^d)&a)^d)+b+x0+u32(0xe9b6c7aa), 20)
|
||||
a = b + bits.rotate_left_32((((b^c)&d)^c)+a+x5+u32(0xd62f105d), 5)
|
||||
d = a + bits.rotate_left_32((((a^b)&c)^b)+d+xa+u32(0x02441453), 9)
|
||||
c = d + bits.rotate_left_32((((d^a)&b)^a)+c+xf+u32(0xd8a1e681), 14)
|
||||
b = c + bits.rotate_left_32((((c^d)&a)^d)+b+x4+u32(0xe7d3fbc8), 20)
|
||||
a = b + bits.rotate_left_32((((b^c)&d)^c)+a+x9+u32(0x21e1cde6), 5)
|
||||
d = a + bits.rotate_left_32((((a^b)&c)^b)+d+xe+u32(0xc33707d6), 9)
|
||||
c = d + bits.rotate_left_32((((d^a)&b)^a)+c+x3+u32(0xf4d50d87), 14)
|
||||
b = c + bits.rotate_left_32((((c^d)&a)^d)+b+x8+u32(0x455a14ed), 20)
|
||||
a = b + bits.rotate_left_32((((b^c)&d)^c)+a+xd+u32(0xa9e3e905), 5)
|
||||
d = a + bits.rotate_left_32((((a^b)&c)^b)+d+x2+u32(0xfcefa3f8), 9)
|
||||
c = d + bits.rotate_left_32((((d^a)&b)^a)+c+x7+u32(0x676f02d9), 14)
|
||||
b = c + bits.rotate_left_32((((c^d)&a)^d)+b+xc+u32(0x8d2a4c8a), 20)
|
||||
|
||||
// round 3
|
||||
a = b + bits.rotate_left_32((b^c^d)+a+x5+u32(0xfffa3942), 4)
|
||||
d = a + bits.rotate_left_32((a^b^c)+d+x8+u32(0x8771f681), 11)
|
||||
c = d + bits.rotate_left_32((d^a^b)+c+xb+u32(0x6d9d6122), 16)
|
||||
b = c + bits.rotate_left_32((c^d^a)+b+xe+u32(0xfde5380c), 23)
|
||||
a = b + bits.rotate_left_32((b^c^d)+a+x1+u32(0xa4beea44), 4)
|
||||
d = a + bits.rotate_left_32((a^b^c)+d+x4+u32(0x4bdecfa9), 11)
|
||||
c = d + bits.rotate_left_32((d^a^b)+c+x7+u32(0xf6bb4b60), 16)
|
||||
b = c + bits.rotate_left_32((c^d^a)+b+xa+u32(0xbebfbc70), 23)
|
||||
a = b + bits.rotate_left_32((b^c^d)+a+xd+u32(0x289b7ec6), 4)
|
||||
d = a + bits.rotate_left_32((a^b^c)+d+x0+u32(0xeaa127fa), 11)
|
||||
c = d + bits.rotate_left_32((d^a^b)+c+x3+u32(0xd4ef3085), 16)
|
||||
b = c + bits.rotate_left_32((c^d^a)+b+x6+u32(0x04881d05), 23)
|
||||
a = b + bits.rotate_left_32((b^c^d)+a+x9+u32(0xd9d4d039), 4)
|
||||
d = a + bits.rotate_left_32((a^b^c)+d+xc+u32(0xe6db99e5), 11)
|
||||
c = d + bits.rotate_left_32((d^a^b)+c+xf+u32(0x1fa27cf8), 16)
|
||||
b = c + bits.rotate_left_32((c^d^a)+b+x2+u32(0xc4ac5665), 23)
|
||||
|
||||
// round 4
|
||||
a = b + bits.rotate_left_32((c^(b|~d))+a+x0+u32(0xf4292244), 6)
|
||||
d = a + bits.rotate_left_32((b^(a|~c))+d+x7+u32(0x432aff97), 10)
|
||||
c = d + bits.rotate_left_32((a^(d|~b))+c+xe+u32(0xab9423a7), 15)
|
||||
b = c + bits.rotate_left_32((d^(c|~a))+b+x5+u32(0xfc93a039), 21)
|
||||
a = b + bits.rotate_left_32((c^(b|~d))+a+xc+u32(0x655b59c3), 6)
|
||||
d = a + bits.rotate_left_32((b^(a|~c))+d+x3+u32(0x8f0ccc92), 10)
|
||||
c = d + bits.rotate_left_32((a^(d|~b))+c+xa+u32(0xffeff47d), 15)
|
||||
b = c + bits.rotate_left_32((d^(c|~a))+b+x1+u32(0x85845dd1), 21)
|
||||
a = b + bits.rotate_left_32((c^(b|~d))+a+x8+u32(0x6fa87e4f), 6)
|
||||
d = a + bits.rotate_left_32((b^(a|~c))+d+xf+u32(0xfe2ce6e0), 10)
|
||||
c = d + bits.rotate_left_32((a^(d|~b))+c+x6+u32(0xa3014314), 15)
|
||||
b = c + bits.rotate_left_32((d^(c|~a))+b+xd+u32(0x4e0811a1), 21)
|
||||
a = b + bits.rotate_left_32((c^(b|~d))+a+x4+u32(0xf7537e82), 6)
|
||||
d = a + bits.rotate_left_32((b^(a|~c))+d+xb+u32(0xbd3af235), 10)
|
||||
c = d + bits.rotate_left_32((a^(d|~b))+c+x2+u32(0x2ad7d2bb), 15)
|
||||
b = c + bits.rotate_left_32((d^(c|~a))+b+x9+u32(0xeb86d391), 21)
|
||||
|
||||
// add saved state
|
||||
a += aa
|
||||
b += bb
|
||||
c += cc
|
||||
d += dd
|
||||
}
|
||||
|
||||
// save state
|
||||
dig.s[0] = a
|
||||
dig.s[1] = b
|
||||
dig.s[2] = c
|
||||
dig.s[3] = d
|
||||
}
|
@ -3,16 +3,17 @@
|
||||
// that can be found in the LICENSE file.
|
||||
|
||||
// Package sha1 implements the SHA-1 hash algorithm as defined in RFC 3174.
|
||||
//
|
||||
|
||||
// SHA-1 is cryptographically broken and should not be used for secure
|
||||
// applications.
|
||||
|
||||
// Adapted from: https://github.com/golang/go/blob/master/src/crypto/sha1
|
||||
|
||||
module sha1
|
||||
|
||||
import math
|
||||
import encoding.binary
|
||||
|
||||
|
||||
const(
|
||||
// The size of a SHA-1 checksum in bytes.
|
||||
Size = 20
|
||||
@ -68,7 +69,7 @@ pub fn (d mut Digest) write(p []byte) ?int {
|
||||
}
|
||||
d.nx += n
|
||||
if d.nx == Chunk {
|
||||
block(d, d.x)
|
||||
block_generic(d, d.x)
|
||||
d.nx = 0
|
||||
}
|
||||
if n >= p.len {
|
||||
@ -79,7 +80,7 @@ pub fn (d mut Digest) write(p []byte) ?int {
|
||||
}
|
||||
if p.len >= Chunk {
|
||||
n := p.len &~ (Chunk - 1)
|
||||
block(d, p.left(n))
|
||||
block_generic(d, p.left(n))
|
||||
if n >= p.len {
|
||||
p = []byte
|
||||
} else {
|
||||
@ -98,14 +99,14 @@ pub fn (d mut Digest) write(p []byte) ?int {
|
||||
pub fn (d &Digest) sum(b_in mut []byte) []byte {
|
||||
// Make a copy of d so that caller can keep writing and summing.
|
||||
mut d0 := *d
|
||||
hash := d0.check_sum()
|
||||
hash := d0.checksum()
|
||||
for b in hash {
|
||||
b_in << b
|
||||
}
|
||||
return *b_in
|
||||
}
|
||||
|
||||
fn (d mut Digest) check_sum() []byte {
|
||||
fn (d mut Digest) checksum() []byte {
|
||||
mut len := d.len
|
||||
// Padding. Add a 1 bit and 0 bits until 56 bytes mod 64.
|
||||
mut tmp := [byte(0); 64]
|
||||
@ -136,10 +137,9 @@ fn (d mut Digest) check_sum() []byte {
|
||||
|
||||
// Sum returns the SHA-1 checksum of the data.
|
||||
pub fn sum(data []byte) []byte {
|
||||
mut d := Digest{}
|
||||
d.reset()
|
||||
mut d := new()
|
||||
d.write(data)
|
||||
return d.check_sum()
|
||||
return d.checksum()
|
||||
}
|
||||
|
||||
pub fn (d &Digest) size() int { return Size }
|
||||
|
@ -1,5 +1,9 @@
|
||||
// Copyright (c) 2019 Alexander Medvednikov. All rights reserved.
|
||||
// Use of this source code is governed by an MIT license
|
||||
// that can be found in the LICENSE file.
|
||||
|
||||
import crypto.sha1
|
||||
|
||||
fn test_crypto_sha1() {
|
||||
assert sha1.sum('This is a sha1 hash.'.bytes()).hex() == '6FF5FA4D5166D5C2576FE56ED1EC2D5AB0FDF936'
|
||||
assert sha1.sum('This is a sha1 checksum.'.bytes()).hex() == 'E100D74442FAA5DCD59463B808983C810A8EB5A1'
|
||||
}
|
||||
|
@ -1,3 +1,9 @@
|
||||
// Copyright (c) 2019 Alexander Medvednikov. All rights reserved.
|
||||
// Use of this source code is governed by an MIT license
|
||||
// that can be found in the LICENSE file.
|
||||
|
||||
// This is a generic implementation with no arch optimizations
|
||||
|
||||
module sha1
|
||||
|
||||
import math.bits
|
||||
@ -9,7 +15,7 @@ const (
|
||||
_K3 = 0xCA62C1D6
|
||||
)
|
||||
|
||||
fn block(dig &Digest, p []byte) {
|
||||
fn block_generic(dig &Digest, p []byte) {
|
||||
mut w := [u32(0); 16]
|
||||
mut h0 := dig.h[0]
|
||||
mut h1 := dig.h[1]
|
||||
@ -73,13 +79,11 @@ fn block(dig &Digest, p []byte) {
|
||||
w[i&0xf] = u32(tmp<<u32(1)) | u32(tmp>>u32(32-1))
|
||||
f := ((b | c) & d) | (b & c)
|
||||
t := bits.rotate_left_32(a, 5) + f + e + w[i&0xf] + u32(_K2)
|
||||
|
||||
e = d
|
||||
d = c
|
||||
c = bits.rotate_left_32(b, 30)
|
||||
b = a
|
||||
a = t
|
||||
|
||||
i++
|
||||
}
|
||||
for i < 80 {
|
Loading…
Reference in New Issue
Block a user