v/vlib/crypto
2025-06-30 21:51:02 +03:00
..
aes crypto.aes: fix notices about order of operations (fix #23898) (#23902) 2025-03-11 14:22:48 +02:00
bcrypt crypt.bcrypt: limit max password length to 72 bytes (#23229) 2024-12-21 13:11:06 +02:00
blake2b blake2s, blake2b: fix typo in new_digest description (#23531) 2025-01-20 06:13:18 +02:00
blake2s blake2s, blake2b: fix typo in new_digest description (#23531) 2025-01-20 06:13:18 +02:00
blake3 checker: disallow struct init with mutable_field: const_array (fix #22862) (#22863) 2024-11-15 11:57:27 +02:00
blowfish fmt: fix alignment of struct init fields (#22025) 2024-08-11 09:11:24 +03:00
cipher crypto: add missing doc comments for public methods (#23864) 2025-03-05 14:36:15 +02:00
des crypto: fix ambiguous expressions in DES implementation (#24814) 2025-06-30 21:51:02 +03:00
ecdsa crypto.ecdsa: add support for OpenSSL on OpenBSD (#24772) 2025-06-22 12:35:30 +03:00
ed25519 checker: add missing check for ref passing to non-ref (#22194) 2024-09-14 23:13:25 +03:00
hmac fmt: remove the prefixed module name of const names, that are in the same module (related #22183) (#22185) 2024-09-10 11:25:56 +03:00
internal/subtle all: change single blank comment to blank line (#22016) 2024-08-09 14:55:58 +03:00
md5 crypto: cleanup the internal constant declarations 2025-01-27 12:08:42 +02:00
pbkdf2 crypto.pbkdf2: move extensive test cases to https://github.com/vlang/slower_tests, but keep test case 7, where the key_size is > block_size for sha224 and sha256 2024-09-13 10:50:55 +03:00
pem all: remove ancient deprecations (#23479) 2025-01-16 16:36:12 +02:00
rand crypto: add missing doc comments for public methods (#23864) 2025-03-05 14:36:15 +02:00
rc4 crypto.rc4: change the return type of new_cipher to be !&Cipher (#24113) 2025-04-03 16:26:11 +03:00
ripemd160 crypto: add a crypto.ripemd160 module (#24119) 2025-04-05 19:05:38 +03:00
scrypt checker: check fn call argument mismatch (fix #23016) (#23061) 2024-12-04 11:52:07 +02:00
sha1 crypto: cleanup the internal constant declarations 2025-01-27 12:08:42 +02:00
sha3 crypto.sha3: be big-endian friendly (#24045) 2025-03-25 23:33:59 +02:00
sha256 crypto: cleanup the internal constant declarations 2025-01-27 12:08:42 +02:00
sha512 crypto: remove unused os import for SHA512 tests (#24768) 2025-06-21 06:28:22 +03:00
crypto.v
README.md crypto: add JWT Payload Decoding sample (#23275) 2024-12-26 16:41:36 +02:00

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
}