2022-01-05 19:06:08 +03:00
|
|
|
## Description:
|
|
|
|
|
2022-01-07 14:28:50 +03:00
|
|
|
`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`.
|
2022-01-05 19:06:08 +03:00
|
|
|
|
|
|
|
The implementations here are loosely based on [Go's crypto package](https://pkg.go.dev/crypto).
|
2022-01-07 14:28:50 +03:00
|
|
|
|
|
|
|
## Examples:
|
|
|
|
|
2022-06-29 11:57:05 +03:00
|
|
|
### AES:
|
2022-01-07 14:28:50 +03:00
|
|
|
```v
|
|
|
|
import crypto.aes
|
|
|
|
import crypto.rand
|
|
|
|
|
|
|
|
fn main() {
|
|
|
|
// remember to save this key somewhere if you ever want to decrypt your data
|
2022-05-13 06:56:21 +03:00
|
|
|
key := rand.bytes(32)?
|
2022-01-07 14:28:50 +03:00
|
|
|
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')
|
2022-04-15 21:08:09 +03:00
|
|
|
mut encrypted := []u8{len: aes.block_size}
|
2022-01-08 18:08:46 +03:00
|
|
|
cipher.encrypt(mut encrypted, data)
|
2022-01-07 14:28:50 +03:00
|
|
|
println(encrypted)
|
|
|
|
|
|
|
|
println('performing decryption')
|
2022-04-15 21:08:09 +03:00
|
|
|
mut decrypted := []u8{len: aes.block_size}
|
2022-01-08 18:08:46 +03:00
|
|
|
cipher.decrypt(mut decrypted, encrypted)
|
2022-01-07 14:28:50 +03:00
|
|
|
println(decrypted)
|
|
|
|
|
|
|
|
assert decrypted == data
|
|
|
|
}
|
|
|
|
```
|
2022-06-29 11:57:05 +03:00
|
|
|
|
|
|
|
### JWT:
|
|
|
|
```v
|
|
|
|
import crypto.hmac
|
|
|
|
import crypto.sha256
|
|
|
|
import encoding.base64
|
|
|
|
import json
|
2022-07-24 10:27:21 +03:00
|
|
|
import time
|
2022-06-29 11:57:05 +03:00
|
|
|
|
|
|
|
struct JwtHeader {
|
|
|
|
alg string
|
|
|
|
typ string
|
|
|
|
}
|
|
|
|
|
|
|
|
struct JwtPayload {
|
|
|
|
sub string
|
|
|
|
name string
|
|
|
|
iat int
|
|
|
|
}
|
|
|
|
|
|
|
|
fn main() {
|
2022-07-24 10:27:21 +03:00
|
|
|
sw := time.new_stopwatch()
|
2022-06-29 11:57:05 +03:00
|
|
|
secret := 'your-256-bit-secret'
|
2022-07-24 10:27:21 +03:00
|
|
|
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')
|
|
|
|
}
|
2022-06-29 11:57:05 +03:00
|
|
|
|
2022-07-24 10:27:21 +03:00
|
|
|
fn make_token(secret string) string {
|
2022-06-29 11:57:05 +03:00
|
|
|
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(),
|
2022-07-24 10:27:21 +03:00
|
|
|
sha256.sum, sha256.block_size))
|
2022-06-29 11:57:05 +03:00
|
|
|
jwt := '${header}.${payload}.$signature'
|
|
|
|
return jwt
|
|
|
|
}
|
2022-07-24 10:27:21 +03:00
|
|
|
|
|
|
|
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)
|
|
|
|
}
|
2022-06-29 11:57:05 +03:00
|
|
|
```
|