0 branches
Tree
Top files
Clone with HTTPS:
rand
Revert "rand: use the OS CSPRNG for `uuid_v4`, `uuid_v7`, `UUIDSession` and `ulid` (#27152)"
last May 14
8.15 KB
crypto.v
crypto: add shake128 and shake256 entries into crypto.Hash enum (#26576)
last Feb 11
237 bytes
Description
crypto is a module that exposes cryptographic algorithms to V programs.
Each submodule implements things differently, so be sure to consider the documentation
of the specific algorithm you need, but in general, the method is to create a cipher
struct using one of the module functions, and then to call the encrypt or decrypt
method on that struct to actually encrypt or decrypt your data.
This module is a work-in-progress. For example, the AES implementation currently requires you
to create a destination buffer of the correct size to receive the decrypted data, and the AesCipher
encrypt and decrypt functions only operate on the first block of the src.
The implementations here are loosely based on Go's crypto package.
Examples
AES
import crypto.aes
import crypto.rand
fn main() {
// remember to save this key somewhere if you ever want to decrypt your data
key := rand.bytes(32)!
println('KEY: ${key}')
// this data is one block (16 bytes) big
mut data := 'THIS IS THE DATA'.bytes()
println('generating cipher')
cipher := aes.new_cipher(key)
println('performing encryption')
mut encrypted := []u8{len: aes.block_size}
cipher.encrypt(mut encrypted, data)
println(encrypted)
println('performing decryption')
mut decrypted := []u8{len: aes.block_size}
cipher.decrypt(mut decrypted, encrypted)
println(decrypted)
assert decrypted == data
}
JWT
import crypto.hmac
import crypto.sha256
import encoding.base64
import json
import time
struct JwtHeader {
alg string
typ string
}
struct JwtPayload {
sub string
name string
iat int
}
fn main() {
sw := time.new_stopwatch()
secret := 'your-256-bit-secret'
token := make_token(secret)
ok := auth_verify(secret, token)
pl := decode_payload(token) or { panic(err) }
dt := sw.elapsed().microseconds()
println('token: ${token}')
println('auth_verify(secret, token): ${ok}')
println('decode_payload(token): ${pl}')
println('Elapsed time: ${dt} uS')
}
fn make_token(secret string) string {
header := base64.url_encode(json.encode(JwtHeader{'HS256', 'JWT'}).bytes())
payload :=
base64.url_encode(json.encode(JwtPayload{'1234567890', 'John Doe', 1516239022}).bytes())
signature := base64.url_encode(hmac.new(secret.bytes(), '${header}.${payload}'.bytes(),
sha256.sum, sha256.block_size))
jwt := '${header}.${payload}.${signature}'
return jwt
}
fn auth_verify(secret string, token string) bool {
token_split := token.split('.')
signature_mirror := hmac.new(secret.bytes(), '${token_split[0]}.${token_split[1]}'.bytes(),
sha256.sum, sha256.block_size)
signature_from_token := base64.url_decode(token_split[2])
return hmac.equal(signature_from_token, signature_mirror)
}
fn decode_payload(token string) !JwtPayload {
token_split := token.split('.')
payload := json.decode(JwtPayload, base64.url_decode_str(token_split[1]))!
return payload
}
Argon2 Password Hashing
import crypto.argon2
fn main() {
hash := argon2.generate_from_password('correct horse battery staple'.bytes())!
println(hash)
argon2.compare_hash_and_password('correct horse battery staple'.bytes(), hash.bytes())!
}