[CryptoAPI] Documentation

[CryptoAPI] Documentation

  
Forge Component
(4)
Published on 2015-11-29 by Ricardo Silva
4 votes
Published on 2015-11-29 by Ricardo Silva
Why did I make this component?

Some of you may be asking why I made this component, since Enterprise Manager already provides a Crypto library.

There are a couple of problems I found with the EnterpriseManager Crypto extension:

1) the encryption scheme used is relatively weak by today's standards. It is not Chosen Plaintext secure, which basically means it's possible to tell when ciphertexts relate to the same plaintext (with the same key), which leaks some information.

2) It uses custom implementations of some of the cryptographic primitives, which is generally a bad practice.

3) It does not use an authenticated encryption schema which means that your data may be tampered without you realizing it.

For reference, the EM Crypto extension uses AES in CBC mode with PKCS7 padding with fixed Initialization Vector. The key derivation for EM Crypto, for interoperability reasons, has custom code in the Java version.

Algorithms used

In this extension I have two encryption schemas. One for randomized encryption and another for deterministic encryption. Both of them provide authenticated encryption, meaning they'll let you know if the ciphertext has been tampered with.

Randomized encryption schema (Encrypt/Decrypt Actions): AES with 256 bit key in CBC mode with PKCS7 padding and randomized Initialization Vector + HMACSHA256 for integrity. I use the same key for confidentiality and integrity. Ciphertext is Base64Encode(iv || E(iv,k,plaintext) || mac(k, iv || E(iv,k,plaintext))

Deterministic encryption schema (Det_Encrypt/Det_Decrypt Actions): AES with 256 bit key in CBC mode with PKCS7 padding and Synthetic Initialization vector taken from the first 16 bytes of the HMACSHA256 mac of the plaintext. I use the same key for confidentiality and integrity. Ciphertext is Base64Encode( MSB(128, mac(k, plaintext)) || E(iv, k, plaintext) ) where MSB(b, v) stands for the b most significant bits (left-most) of v.

Asymmetric encryption schema uses RSA with OAEP padding with the common MFG1 and SHA1 functions as parameters.

Integrity schema (ComputeMac action): HMACSHA256 with 256 bit key.

Key derivation (DeriveKey action): RFC 2898 PBKDF2 with fixed 128 byte salt using HMACSha1 as the underlying mac algorithm with 37649 iterations.

All crypto implementations are taken from either .NET framework crypto library or from bouncy castle (in Java).

Data (strings) are utf-8 encoded prior to encryption and utf-8 decoded upon decryption. 

Bulk processing

If you want to process a lot of data with the same key, you can use the K* version of the actions to avoid deriving the key for each encryption/mac. This is also one of the reasons why key derivation uses a fixed salt. If the salt was unique per encryption you couldn't bulk process anything since you couldn't pre-process the key.

What should I use?

If you're looking to just encrypt some data, you should use the Encrypt family of actions.

If you want to add some encrypted field as searchable, you can use the Det_Encrypt family of actions. In order to maintain security you should make sure that you do not use the same key to encrypt the same data twice on the database (the attribute holding the encrypted data should have a unique constraint)

Further discussion.
Ricardo, love your work!
Great extension.
Just 1 remark/question; the "DeriveKey" action seems to consistently take somewhere between 700ms and 1200ms. Anyone else noticing this?
Hello Tim,

sorry for the late reply, but yes: key derivation is meant to be slow (to prevent brute force attacks). As the action says, it does 37649 hmacsha1 operations.

Best regards,
Ricardo Silva
erm,

silly me, any examples?

i want encrypt a password with HMAC-SHA256 and compare it with a password i got (which i know is samely encrypted with ofcourse the same shared key)
Crypto API purposefully only covers symmetric encryption schemas, and doesn't have any support for one-way MACs or functions, so your specific use-case will not be possible with Crypto API.

The closest you have here would be the deterministic encryption schema, but that is a two-way cipher. For storing passwords you should try and use one-way hash functions (SHA256, MAC's).
Hi guys. I don't know if it helps the discussion, but I came across with the necessity of performing strong one-way hasing on OutSystems platform to develop a component that resembles an OAuth 2.0 provider.
I used CryptoAPI and used the function that encrypts data with a password, being the password a concatenation of two GeneratePassword(10,true) functions.
As the two GeneratePassword functions will yield a pseudo-random string with 10 characters (numbers and letters), I believe that the 20 characters will be enough (I called twice the function so that I had two different seeds and, in theory, have a bit more "random" string).
As in my code, the GeneratePassword() calls are inside the encrypt funcion of CryptoAPI, there's no way for an user to know the key that the original string was encrypted with.

Naturally I know that this only works for fixed-length inputs as this is not a normal "Hash" (MD5, SHA-1, SHA256) function that will only returns fixed-length outputs for any input length, but if you, like me, are working with security tokens, it is good enough.

One suggestion that I leave for Ricardo here would be to implement simple SHA256 Hashing functions to this extension. It would be a god send for most of us that use it.

Hope it helps.
Fábio

Hello Statler,

I have just added a new version of this component which supports password hashing out of the box.

It has two functions: HashPassword and ComparePassword. You can use the first to securely hash a password for storage in a database ( SHA512 with random 24 byte salt ) and the second to compare an existing hash to see if it matches a given password.

Using HMAC for this kind of use is weird as it requires an extra key to be known on both sides.

This should cover your password needs, let me know if you have further questions regarding this.

@ Fábio, SHA256 is also now implemented in CryptoAPI.

Best regards,
Ricardo Silva
Hi,

I might need to encrypt some data-columns in my database (customernames)
I am curious how to approach this. where should I store my public/private key?

I am thinking of creating some keys on my dev-environment and store the key in my espace?
different keys for acc, production and test?



Hello Statler & Waldorf. I have answered that question in a separate thread.
Ricardo I need yout help.

I need encryption a string , example:
string for encyption -

login=1009512&senha=minhasenha&data=2015-05-20T09:15:38-03:00
format RSA-SHA256 and using key públic in file XML or PEM.

and convert in Base64

How i do? its api enables this?

thanks!

what does KEncrypt and KDecrypt function parameters ,can u give me an example for both 


I mean to say Inwhat Format both are passed
KEncrypt takes two parameters, a key ( Binary Data ) and text to encrypt.

You can generate the key by using the GenerateAESKey function.

KDecrypt takes a result from KEncrypt and a key (the same that was used to encrypt) to turn the encrypted text into the text again.