## 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](https://pkg.go.dev/crypto).

## Examples

### AES

```v
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

```v
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
}
```