1
0
mirror of https://github.com/vlang/v.git synced 2023-08-10 21:13:21 +03:00
v/vlib/crypto
2023-01-16 13:23:46 +02:00
..
aes vfmt: implement support for // vfmt off and // vfmt on, with it, v fmt -w . now works. (#16335) 2022-11-05 09:08:01 +03:00
bcrypt bcrypt: fix issue #16769 security problem in compare_hash_and_password (#16815) 2022-12-31 17:18:43 +02:00
blowfish all: replace []byte with []u8 2022-04-15 15:35:35 +03:00
cipher all: replace []byte with []u8 2022-04-15 15:35:35 +03:00
des ci: fix ./v -progress test-cleancode 2022-04-15 21:04:10 +03:00
ed25519 all: replace generic <> with [] - part 2 (#16536) 2022-11-26 18:23:26 +02:00
hmac vfmt: fix array_init line wrapping (#14154) 2022-04-25 08:11:44 +03:00
internal/subtle all: replace []byte with []u8 2022-04-15 15:35:35 +03:00
md5 checker: check int overflow for const vars (#16332) 2022-11-06 08:22:28 +03:00
rand vfmt: change all '$expr' to '${expr}' (#16428) 2022-11-15 16:53:13 +03:00
rc4 all: change optional to result in most of the libraries (#16123) 2022-10-20 22:14:33 +03:00
sha1 checker: check int overflow for const vars (#16332) 2022-11-06 08:22:28 +03:00
sha256 crypto.sha256: add .free() and .reset() methods to reduce memory leaks with -autofree (#16991) 2023-01-16 13:23:46 +02:00
sha512 vfmt: implement support for // vfmt off and // vfmt on, with it, v fmt -w . now works. (#16335) 2022-11-05 09:08:01 +03:00
crypto.v tools: make v test-cleancode test everything by default (#10050) 2021-05-08 13:32:29 +03:00
README.md vfmt: change all '$expr' to '${expr}' (#16428) 2022-11-15 16:53:13 +03: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)
	dt := sw.elapsed().microseconds()
	println('token: ${token}')
	println('auth_verify(secret, token): ${ok}')
	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)
}