From eb314c93a2b34bb32c631308ed3c78aa3320dd17 Mon Sep 17 00:00:00 2001 From: Roman <90373295+sibkod@users.noreply.github.com> Date: Fri, 16 Aug 2024 00:01:06 +0700 Subject: [PATCH] crypto: add a crypto.pbkdf2 module (#22047) --- vlib/crypto/pbkdf2/pbkdf2.v | 58 ++++++++++++++++++++++++++++++++ vlib/crypto/pbkdf2/pbkdf2_test.v | 18 ++++++++++ 2 files changed, 76 insertions(+) create mode 100644 vlib/crypto/pbkdf2/pbkdf2.v create mode 100644 vlib/crypto/pbkdf2/pbkdf2_test.v diff --git a/vlib/crypto/pbkdf2/pbkdf2.v b/vlib/crypto/pbkdf2/pbkdf2.v new file mode 100644 index 00000000000000..a321c4573e21f8 --- /dev/null +++ b/vlib/crypto/pbkdf2/pbkdf2.v @@ -0,0 +1,58 @@ +// Based off: https://golang.org/x/crypto/pbkdf2 +module pbkdf2 + +import crypto.hmac +import crypto.sha256 +import crypto.sha512 +import hash + +// key derives a key from the password, salt and iteration count +// example pbkdf2.key('test'.bytes(), '123456'.bytes(), 1000, 64, sha512.new()) +pub fn key(password []u8, salt []u8, count int, key_length int, h hash.Hash) ![]u8 { + mut fun := fn (b []u8) []u8 { + return []u8{} + } + mut block_size := 0 + mut size := 0 + match h { + sha256.Digest { + fun = sha256.sum256 + block_size = sha256.block_size + size = sha256.size + } + sha512.Digest { + fun = sha512.sum512 + block_size = sha512.block_size + size = sha512.size + } + else { + panic('Unsupported hash') + } + } + + hash_length := size + block_count := (key_length + hash_length - 1) / hash_length + mut output := []u8{} + mut last := []u8{} + mut buf := []u8{len: 4} + for i := 1; i <= block_count; i++ { + last << salt + + buf[0] = u8(i >> 24) + buf[1] = u8(i >> 16) + buf[2] = u8(i >> 8) + buf[3] = u8(i) + + last << buf + mut xorsum := hmac.new(password, last, fun, block_size) + mut last_hash := xorsum.clone() + for j := 1; j < count; j++ { + last_hash = hmac.new(password, last_hash, fun, block_size) + for k in 0 .. xorsum.len { + xorsum[k] ^= last_hash[k] + } + } + output << xorsum + } + return output[..key_length] +} diff --git a/vlib/crypto/pbkdf2/pbkdf2_test.v b/vlib/crypto/pbkdf2/pbkdf2_test.v new file mode 100644 index 00000000000000..35ad0cbd7da8b0 --- /dev/null +++ b/vlib/crypto/pbkdf2/pbkdf2_test.v @@ -0,0 +1,18 @@ +import crypto.sha512 +import crypto.sha256 +import crypto.pbkdf2 + +const data = 'test' +const password = '123456' + +fn test_sha512() { + // vfmt off + assert pbkdf2.key(data.bytes(), password.bytes(), 1000, 64, sha512.new())! == [u8(149) 155 168 16 77 243 26 192 128 222 29 139 38 173 131 82 73 152 197 253 66 64 11 103 32 110 95 116 143 4 104 70 176 24 99 48 224 77 47 184 193 59 98 191 18 172 4 119 83 93 198 101 118 131 223 150 215 172 170 166 205 187 247 160] + // vfmt on +} + +fn test_sha256() { + // vfmt off + assert pbkdf2.key(data.bytes(), password.bytes(), 1000, 32, sha256.new())! == [u8(110) 95 68 212 254 34 114 21 43 19 155 141 36 158 236 51 16 244 85 107 245 172 219 25 128 109 111 18 25 14 9 149] + // vfmt on +}