ScrimpNet.Cryptography Documentation

 

The Task: You want to quickly begin using encryption and/or hashing in your program; perhaps by just providing a password.

The Problem:  The .Net encryption API’s are extremely flexible and you have control over each aspect of the process.  As with everything, “flexibility breeds complexity” and .Net does not really provide an easy way to encrypt you data.  You have to be familiar with concepts such as block sizes, random number generators, padding, encoding, keys, initialization vectors, collision spaces, and even hacking trends.

The Solution:  CryptoUtils is a wrapper class that hides the complexity (well almost all) that is inherent in traditional crypto APIs.  Under the covers, it uses the standard .Net encryption/hashing algorithms so you can be assured the library is as strong (or as weak) as the .Net library it’s self.  There are two variants but you can start with CryptoUtils.Simple.  The other API, CryptoUtils.Machine, is geared toward encryption within web-farms  and is helpful when you are concerned about separation of duties or data leakage between production and development environments.

CryptoUtils.Simple

  • Simple API (three methods: Encode, Decode, Hash)
  • All results are returned  as a Base64 formatted string.  Thus it is suitable for including in .config files, database text fields, emails, etc.
  • Each API has three consistent overloads (string, object, byte array) so you can encrypt/hash most anything you need
  • Uses reasonable defaults. (Rijindael with 256bit keys for encryption, SHA256 for simple hashing, HMACSHA256 for salted hashing)
  • Encryption based on a ‘password’ (‘passphrase’) or any arbitrary piece of text you want to use as the key
  • Defaults can be changed
  • A simple unit test is provided that demonstrates each variant

Encrypting Strings

string secretNumber = CryptoUtils.Simple.Encode(“My Secret Winning Lotto Numbers”,”Open Sesame”);

string winningNumber = CryptoUtils.Simple.Decode(secretNumber,”Open Sesame”);

Encrypting Objects

When encrypting entire objects, the object must be binary serializable.

var userProfile = new UserProfile();

string encryptedProfile = CryptoUtils.Simple.Encode(userProfile,”Open Sesame”);

var userProfileUnencrypted = CryptoUtils.Simple.Decode<UserProfileClass>(encryptedProfile,”Open Sesame”);

Encrypting Bytes

If you want to deal with byte arrays directly, you can use the byte[] overloaded function.  Remember you can use one of the CryptoUtils.FromBytes functions to convert a byte array to various types of strings.

byte[] secretBytes = CryptoUtils.Simple.Encode(myByteArray,”Open Sesame”);

byte[] normalBytes = CryptoUtils.Simple.Decode(secretBytes,”Open Desame”);

Hashing Overview

Hashing creates a unique ‘signature’ of a block of data and cannot be reverse engineered.  This makes it ideal for storing things like passwords which should never be retrieved but must remain unique.  A hash ‘salt’ scrambles the data even more and makes it significantly harder for a hacker to break a hash (e.g. when a password table is stolen).  Which you choose is a matter of preference and design trade-offs.  For password and identity hashing you should always use a ‘salt’.

A ‘salt’ can be any random piece of text and should be protected along side other confidential password and keys.  If you don’t have a preference or are not exchanging this hash with somebody outside your organization, you might use the CryptoUtils.Generate.Salt() function to create a salt for you.  If the ‘salt’ is compromised your data is still very secure; just somewhat less than without it.  Don’t risk it.  Protect your ‘salt’.

Hashing Strings

string passwordHash = CryptoUtils.Simple.Hash(“simple message that you shouldn’t change”);

string passwordHashSalted  = CryptoUtils.Simple.Hash(“my password”, “fair skys and following seas”);

Hashing Objects

string hashedObject = CryptoUtils.Simple.Hash(emailMessage);

Hashing Bytes

If you want to deal with byte arrays directly, you can use the byte[] overloaded function. Remember you can use one of the CryptoUtils.FromBytes functions to convert a byte array to various types of strings.

byte[] hashedBytes = CryptoUtils.Simple.Hash(imageBytes);

CryptoUtils.Machine

This wrapper exposes an extremely powerful set of encryption capabilities; especially when used within the context of web applications (farm or gardens) and multi-tier,multi-server, multi-environment scenarios.

  • Simple API (three methods: Encode, Decode, Hash)
  • All results are returned as a Hex formatted string. Thus it is suitable for including in .config files, database text fields, emails, etc.
  • Each API has three consistent overloads (string, object, byte array) so you can encrypt/hash most anything you need
  • Uses .Net framework’s embedded <machineKey> (usually found in machine.config).  No key/password management hassles to worry about.
  • A simple unit test is provided that demonstrates each variant
  • Does not use ‘salted’ hash
  • Helps support a good “Separation of Duties” provision necessary for some compliance and certification efforts. (see below)
  • Helps prevent sensitive production data from leaking into backup store or into non-secure environments (development, staging, testing, etc.)

Encrypting Strings

string secretNumber = CryptoUtils.Machine.Encode(“My Secret Winning Lotto Numbers”);

string winningNumber = CryptoUtils.Machine.Decode(secretNumber);

Encrypting Objects

When encrypting entire objects, the object must be binary serializable.

var userProfile = new UserProfile();

string encryptedProfile = CryptoUtils.Machine.Encode(userProfile);

var userProfileUnencrypted = CryptoUtils.Machine.Decode<UserProfileClass>(encryptedProfile);

Encrypting Bytes

If you want to deal with byte arrays directly, you can use the byte[] overloaded function. Remember you can use one of the CryptoUtils.FromBytes functions to convert a byte array to various types of strings.

byte[] secretBytes = CryptoUtils.Simple.Encode(myByteArray);

byte[] normalBytes = CryptoUtils.Simple.Decode(secretBytes);

Hashing Overview

Hashing creates a unique ‘signature’ of a block of data and cannot be reverse engineered. This makes it ideal for storing things like passwords which should never be retrieved but must remain unique.

Hashing Strings

string passwordHash = CryptoUtils.Machine.Hash(“simple message that you shouldn’t change”);

Hashing Objects

string hashedObject = CryptoUtils.Machine.Hash(emailMessage);

Hashing Bytes

If you want to deal with byte arrays directly, you can use the byte[] overloaded function. Remember you can use one of the CryptoUtils.FromBytes functions to convert a byte array to various types of strings.

byte[] hashedBytes = CryptoUtils.Machine.Hash(imageBytes);

Questions About The Library

How does CryptoUtils.Machine encourage ‘Separation of Duties’?

CryptoUtils.Machine uses the .Net framework’s embedded <machineKey> to perform it’s cryptologic operations.  ‘Separation of Duties’ is about keeping functions distinct: key creation and maintenance, key usage, and encrypted data storage.  Those creating a key, shouldn’t be able to use the key they created; those using the key shouldn’t be able to create or change the key; and those storing encrypted data shouldn’t be able to decrypt the data.

With the CrytoUtils.Machine library  some good separations are relatively easy to implement:

  • System operations provisions a common key to the machine.config file of each computer generating encrypted data.  Application developers (indeed even the applications themselves) and DBA’s do not have access to these keys
  • Applications never touch the the keys, they submit data to an internal service which performs the requested operation.  Encrypted/hashed data is stored in database.
  • DBA’s do not have access to keys nor to the encryption algorithm used.  They can store, backup, restore encrypted records but they can not discern their content.

How does CryptoUtils.Machine help prevent data leaks across environments?

“Data Leakage” happens when secured data is copied from it’s source to an non-secure environment.   This can happen when seed data is generated in a development and copied to production.  For instance development username’s and passwords make it into production.  PCI (e.g. credit card numbers), PII (e.g SSN, birth days), or security information (bank account numbers) often slip into staging or Q/A environments in order to facility better debugging of a difficult situation.  Often production table(s) are restored into a different environment while debugging a critical problem in “crises” mode.  When the event is over, the data is often not purged and secure data is now sitting in an unsecured environment.

CryptoUtils.Machine uses encryption keys explicitly provisioned on each server; usually only the web application servers and *NOT* on the database servers.  When data is “accidently” copied out of a secure environment they encryption keys are not copied.  So, even if data is not living in an unsecure environment, it can not be decrypted, passwords cannot be validated, or secure transactions be initiated.

How do I change the default CryptoUtils.Simple encryption settings?

All the configurable parameters are defined as private constants at top of of the CryptoUtils.Simple.cs class.  The settings include:

KEYBYTES Number of bytes to use for symmetric key operations.  .Net symmetric algorithms have different valid block sizes.  Be sure to convert bits (usually used in cryptographic discussions) to bytes.
KEYIV Number of bytes to use for initialization vector.  .Net symmetric algorithms have different valid block sizes. Be sure to convert bits (usually used in cryptographic discussions) to bytes.
EncryptionMode Any one of the .Net Symmetric encryption modes.  These are defined in the Crypto.EncodeModes constants.
InternalSalt Sequence of random bytes used when generating random keys.  While you don’t necessarily have to change these, it is good cryptologic practice to never use a salt that is published in code.  You can use the CryptoUtils.Generate.RandomBytesCS() which returns a string suitable for pasting into C# code.  You should choose a length of at least 16 characters.
StringFormat Format of string that is returned from the functions.  Either Base64, Hex, or Unicode
SimpleHashMode Any one of the .Net hash modes.  Use one of the Crypto.HashModeSimple constants
SaltedHashMode Any one of the .Net salted hash modes.  Use one of the Crytpo.HashModesSalted

What are the supported return string formats?

Strings in the library is one of Base64, Hex, or Unicode.  Base64 and Hex are self-explanatory.  Unicode is a binary representation of the returned value and is the shortest (by length) representation.

You can use the CryptoUtils.FromBytes and CryptoUtils.ToBytes to convert between different string types.

What .Net Crypto Libraries are supported?

CryptoUtils library supports the following .Net encryption libraries but only one library from each column can be set within CryptoUtils.Simple and are hard coded into the class (That’s what makes it simple!).

Encryption Hashed (Simple) Hashed (Salt)
AES MD5 HMAC-MD5
DES SHA1 HMAC-SHA1
RC2 SHA256 (*) HMAC-SHA256 (*)
Rijindael (*) SHA384 HMAC-SHA385
TripleDES SHA512 HMAC-SAH512
  RIPEMD160 HMAC-RIPEMD160
    HMAC-TripleDES

(*) Default setting

Last edited Sep 5, 2011 at 2:13 AM by DrIO, version 4

Comments

No comments yet.