Crate crypter

Crate crypter 

Source
Expand description

The crypter crate provides Rust and FFI easy encryption and decryption using AES-GCM-SIV 256-bits.

§Features

NameDescription
ffiEnables the C API
wasmEnables the WASM API
streamEnables streamming for encryption/decryption
argonEnables key derivation using Argon2id

See the examples for working FFI applications.

§Examples

let key = get_key();
let payload = "mega ultra safe payload";

let encrypted = crypter::encrypt(&key, payload).expect("Failed to encrypt");
let decrypted = crypter::decrypt(&key, encrypted).expect("Failed to decrypt");
println!("{}", String::from_utf8(decrypted).expect("Invalid decrypted string"));

§FFI examples

§C example: example.c

#include <stdio.h>
#include <string.h>

#include <crypter.h>

CrypterKey get_key();

int main() {
#include <stdio.h>

#include <crypter.h>

int main() {
  const char *payload = "mega ultra safe payload";

  CrypterKey key = get_key();

  CrypterRustSlice encrypted = crypter_encrypt(
      &key, (CrypterCSlice){.ptr = (const unsigned char *)payload,
                            .len = strlen(payload)});

  CrypterCSlice encrypted_slice = {.ptr = encrypted.ptr, .len = encrypted.len};

  CrypterRustSlice decrypted = crypter_decrypt(&key, encrypted_slice);

  if (decrypted.ptr) {
    for (int i = 0; i < decrypted.len; i++) {
      if (decrypted.ptr[i] == 0) {
        putchar('0');
      } else {
        putchar(decrypted.ptr[i]);
      }
    }
    putchar('\n');
  } else {
    puts("Null return");
  }

  crypter_free_slice(&encrypted);
  crypter_free_slice(&decrypted);
}

§Lua example: example.lua

local ffi = require('ffi')

ffi.cdef [[
  typedef uint8_t Key[32];
  typedef struct Slice { const uint8_t *ptr; uintptr_t len; } Slice;
  typedef struct RustSlice { const uint8_t *ptr; uintptr_t len; uintptr_t cap; } RustSlice;

  RustSlice crypter_encrypt(const Key *key, struct Slice payload);
  RustSlice crypter_decrypt(const Key *key, struct Slice payload);
  void crypter_free_slice(struct RustSlice *slice);
]]

local function slice_from_str(text)
  return ffi.new('Slice', { ptr = ffi.cast('uint8_t *', text), len = #text })
end

local function relax_rust_slice(rust_slice)
  return ffi.new('Slice', { ptr = rust_slice.ptr, len = rust_slice.len })
end

crypter = ffi.load('crypter')

local key = require('my_key_getter').get_key()
local payload = 'mega ultra safe payload'
local payload_slice = slice_from_str(payload)
local encrypted = crypter.crypter_encrypt(key, payload_slice)
local decrypted = crypter.crypter_decrypt(key, relax_rust_slice(encrypted))

if decrypted.ptr ~= nil then
  print(ffi.string(decrypted.ptr, decrypted.len))
else
  print('Failed roud trip')
end

crypter.crypter_free_slice(encrypted)
crypter.crypter_free_slice(decrypted)

§WASM example: index.html

<!DOCTYPE html>
<html>
  <head>
    <meta http-equiv="Content-type" content="text/html; charset=utf-8" />
    <title>crypter</title>
  </head>
  <body>
    <script type="module">
      import init from "./crypter.js";

      init("./crypter_bg.wasm").then(() => {
        const crypter = import('./crypter.js');
        crypter.then(c => {
          const encoder = new TextEncoder();
          const key = encoder.encode('super_mega_ultra_secret_01234567'); // Bad key. Just as an example
          const encrypted = c.encrypt(key, encoder.encode('mega ultra safe payload'));
          const decrypted = c.decrypt(key, encrypted);
          console.log('Encrypted: ', new TextDecoder().decode(decrypted));
        });
      });
    </script>
  </body>
</html>

Modules§

streamstream
Stream support for AES-GCM-SIV 256-bits encrypting and decrypting in chunks.

Functions§

decrypt
Decrypts the payload with AES256 GCM SIV.
decrypt_with_passwordargon
Decrypts the payload with AES256 GCM SIV using a key derived from password with Argon2.
encrypt
Encrypts the payload with AES256 GCM SIV. The iv is randomly generated for each call.
encrypt_with_passwordargon
Encrypts the payload with AES256 GCM SIV using a key derived from password with Argon2. The iv and the salt are randomly generated for each call.