8 releases

0.1.6 Dec 10, 2020
0.1.5 Nov 16, 2020
0.0.1 Aug 4, 2020

#2016 in Cryptography

Apache-2.0

165KB
2K SLoC

YACA bindings for Rust

crate docs license repo

YACA library is required for the bindings to work.

YACA - Yet Another Crypto API

YACA is a simple, yet powerful wrapper for the OpenSSL library. It wraps common and most widely used cryptographic operations in a simple and easy to use API.

See the documentation's main page for a quick example.
tests directory contains more tests/examples for all available APIs.


lib.rs:

YACA - Yet Another Crypto API. Bindings for C library YACA

Examples

use std::ffi::CString;
use yaca::{self, prelude::*};
use yaca::{Key, KeyType, KeyLength, KeyFormat, KeyFileFormat, EncryptContext,
          DecryptContext, EncryptAlgorithm, BlockCipherMode, Padding};

pub const MSG: &[u8] = b"Lorem ipsum dolor sit amet.";

fn main() -> Result<(), Box<dyn std::error::Error>>
{
   // Start

   yaca::initialize()?;

   // Key generate/export/import example:

   let key = Key::generate(&KeyType::RsaPrivate,
                           &KeyLength::Bits(512))?;
   let p = CString::new("password")?;
   let data = key.export(&KeyFormat::Default, &KeyFileFormat::Pem, Some(&p))?;
   let key = Key::import(&data, &KeyType::RsaPrivate, Some(&p))?;

   println!("{:?}: {:?}", key.get_type()?, key.get_length()?);

   // Encrypt/decrypt example:

   // Prepare

   let algo = EncryptAlgorithm::Aes;
   let cbc = BlockCipherMode::Cbc;
   let key_len = KeyLength::Bits(256);
   let sym_key = Key::generate(&KeyType::Symmetric, &key_len)?;
   let iv_len = EncryptContext::get_iv_length(&algo, &cbc, &key_len)?;
   let iv = match &iv_len {
       None => None,
       Some(x) => Some(Key::generate(&KeyType::Iv, x)?),
   };
   if let Some(x) = &iv {
       println!("IV_used: {:?}: {:?}", x.get_type()?, x.get_length()?);
   };

   // Encrypt

   let ctx = EncryptContext::initialize(&algo, &cbc, &sym_key, iv.as_ref())?;
   ctx.set_property_padding(&Padding::Pkcs7)?;
   let mut cipher: Vec<u8> = Vec::new();
   for i in MSG.chunks(5) {
       cipher.append(&mut ctx.update(i)?);
   };
   cipher.append(&mut ctx.finalize()?);

   // Decrypt

   let ctx = DecryptContext::initialize(&algo, &cbc, &sym_key, iv.as_ref())?;
   ctx.set_property_padding(&Padding::Pkcs7)?;
   let mut plain: Vec<u8> = Vec::new();
   for i in cipher.chunks(5) {
       plain.append(&mut ctx.update(i)?);
   };
   plain.append(&mut ctx.finalize()?);

   // Check

   assert_eq!(MSG, plain);
   let plain = CString::new(plain)?;
   println!("{}", plain.to_str()?);

   // Finish

   Ok(yaca::cleanup())
}

Simple API:

Defined by functions named Yaca::simple_*

Design constraints:

  • All operations are single-shot (no streaming possible)
  • Context is not used
  • Only digest, signatures and symmetric ciphers are supported
  • Disabling PKCS#7 padding for ECB and CBC chaining is not supported
  • Changing the default PKCS#1 padding for sign/verify is not supported
  • GCM and CCM chaining is not supported
  • RC2 effective key bits property is not supported
use std::ffi::CString;
use yaca::{self, prelude::*};
use yaca::{Key, KeyType, KeyLength, EncryptAlgorithm, BlockCipherMode};

pub const MSG: &[u8] = b"Lorem ipsum dolor sit amet.";

fn main() -> Result<(), Box<dyn std::error::Error>>
{
   // Start
   yaca::initialize()?;

   // Simple encrypt/decrypt of empty data
   let sym_key = Key::generate(&KeyType::Symmetric, &KeyLength::Bits(256))?;
   let v = yaca::simple_encrypt(&EncryptAlgorithm::UnsafeRc4, &BlockCipherMode::None,
                                &sym_key, None, &Vec::new())?;
   assert!(v.is_empty());
   let v = yaca::simple_decrypt(&EncryptAlgorithm::UnsafeRc4, &BlockCipherMode::None,
                                &sym_key, None, &Vec::new())?;
   assert!(v.is_empty());

   // Simple encrypt/decrypt
   let iv = Key::generate(&KeyType::Iv, &KeyLength::Bits(128))?;
   let cipher = yaca::simple_encrypt(&EncryptAlgorithm::Aes, &BlockCipherMode::Cbc,
                                     &sym_key, Some(&iv), MSG)?;
   let plain = yaca::simple_decrypt(&EncryptAlgorithm::Aes, &BlockCipherMode::Cbc,
                                    &sym_key, Some(&iv), &cipher)?;

   // Check for simple
   assert_eq!(MSG, plain);
   let plain = CString::new(plain)?;
   println!("{}", plain.to_str()?);

   // Finish
   Ok(yaca::cleanup())
}

Dependencies

~250KB