a developers guide to encryption

50
A Developer’s Guide to Encryption Barry Dorrans MVP – Developer Security (well for 9 more days anyway) [email protected]

Upload: technical-dude

Post on 06-May-2015

1.958 views

Category:

Documents


0 download

TRANSCRIPT

Page 1: A Developers Guide to Encryption

A Developer’s Guide to Encryption

Barry DorransMVP – Developer Security

(well for 9 more days anyway)[email protected]

Page 2: A Developers Guide to Encryption

A Developer’s Guide to Encryption

• What is cryptography?• Random Numbers• Hashing• Symmetric Encryption– Deriving keys from passwords

• Asymmetric Encryption– Manual Asymmetric Encryption– X509 Certificates

• Message Authentication Codes• Encrypting and Signing XML

Page 3: A Developers Guide to Encryption

What is cryptography?

• This session will not include mathematics.

• Cryptography - the study of techniques and applications that depend on the existence of difficult problems.

• Cryptanalysis - the study of how to compromise (defeat) cryptographic mechanisms.

• Cryptology - (from the Greek “kryptós lógos” meaning “hidden word”) is the discipline of cryptography and cryptanalysis combined.

Page 4: A Developers Guide to Encryption

Definitions

• Plaintext / Cleartext – Unencrypted Data.

• Ciphertext –Encrypted Data.

• Cipher –Encryption algorithm.

Page 5: A Developers Guide to Encryption

Random Numbers

• Cryptography needs random numbers.

• Random isn’t really random.

• PRNG – Pseudo Random Number Generator.

Page 6: A Developers Guide to Encryption

Cryptographically Secure Random Numbers

• System.Security.Cryptography.RandomNumberGenerator

public static byte[] GenerateRandomBytes(int length){ byte[] randomArray = new byte[length]; RNGCryptoServiceProvider rng = new RNGCryptoServiceProvider(); rng.GetBytes(randomArray); return randomArray;}

Page 7: A Developers Guide to Encryption

Hardware RNGs

• Based on– Radioactive decay,– Background noise,– Other entropy source.

• Specialised Hardware.• But now even Intel

Chipsets have hardware RNGs.

• (Post Office Ernie)

Page 8: A Developers Guide to Encryption

Hashing

• A well-defined procedure or mathematical function that converts a large, possibly variable-sized amount of data into a small datum.

• One way.• Typically used for

passwords, checksums.

Page 9: A Developers Guide to Encryption

Generating a hashHashAlgorithm algorithm = new SHA256Managed();byte[] hash = algorithm.ComputeHash(plaintext);

Page 10: A Developers Guide to Encryption

Hash Algorithms

• MD Family (MD2, MD4, MD5)• SHA Family (SHA1, SHA2, SHA3)• Whirlpool

• MD*, SHA1 are no longer considered secure• SHA2 are the most commonly used• Whirlpool is the newest ISO standard.

No implementation in the .NET framework.

Page 11: A Developers Guide to Encryption

Salting the hash

• Salting adds a random piece of data to the plaintext.

• Stops pre-computed lookups and rainbow tables.

• Never hash without salt.

• Salts can be stored beside the hash.

Page 12: A Developers Guide to Encryption

Salting a hashHashAlgorithm algorithm = new SHA256Managed();

byte[] plainTextWithSaltBytes = new byte[plainText.Length + salt.Length];

for (int i = 0; i < plainText.Length; i++){ plainTextWithSaltBytes[i] = plainText[i];}for (int i = 0; i < salt.Length; i++){ plainTextWithSaltBytes[plainText.Length + i] = salt[i];}

byte[] hash = algorithm.ComputeHash(plainTextWithSaltBytes);

Page 13: A Developers Guide to Encryption

Comparing byte arrayspublic static bool CompareByteArrays( byte[] array1, byte[] array2){ if (array1.Length != array2.Length) return false;

for (int i = 0; i < array1.Length; i++) { if (array1[i] != array2[i]) return false; }

return true;}

Page 14: A Developers Guide to Encryption

Demo Time!

Page 15: A Developers Guide to Encryption

Encryption Keys

• Once you lose them change the “locks”.

• Keys are like condoms -don’t reuse them.

Page 16: A Developers Guide to Encryption

Symmetric Encryption

• A single key is used for encryption and decryption.

• Fast, computationally cheap.

• Needs a shared key.• Repudiable.

Page 17: A Developers Guide to Encryption

Symmetric Keys

• Keys are cryptographically secure random data.

• Size of key depends on algorithm.

Page 18: A Developers Guide to Encryption

Initialization Vectors

• Symmetric algorithms tend to be block algorithms.

• The result of a block encryption feeds into the next block.

• An IV is the initial starting block.

• An IV is cryptographically secure random data

Page 19: A Developers Guide to Encryption

Demo Time!

Page 20: A Developers Guide to Encryption

Encrypting SymmetricallyRijndaelManaged rijndaelManaged = new RijndaelManaged();ICryptoTransform cryptoTransform = rijndaelManaged.CreateEncryptor(

key, IV);

MemoryStream outputStream = new MemoryStream();CryptoStream cryptoStream = new CryptoStream(

outputStream,cryptoTransform,CryptoStreamMode.Write);

cryptoStream.Write(plaintextAsBytes, 0,plaintextAsBytes.Length);

cryptoStream.FlushFinalBlock();

byte[] ciphertextAsBytes = outputStream.ToArray();

Page 21: A Developers Guide to Encryption

Decrypting SymmetricallyRijndaelManaged rijndaelManaged = new RijndaelManaged();ICryptoTransform cryptoTransform = rijndaelManaged.CreateDecryptor(

key, IV);

MemoryStream outputStream = new MemoryStream();CryptoStream cryptoStream = new CryptoStream(

outputStream,cryptoTransform,CryptoStreamMode.Write);

cryptoStream.Write(plaintextAsBytes, 0,plaintextAsBytes.Length);

cryptoStream.FlushFinalBlock();

byte[] ciphertextAsBytes = outputStream.ToArray();

Page 22: A Developers Guide to Encryption

Symmetric Encryption Algorithms

• DES• TripleDES• Rivest Cipher 2• Rijndael/AES

• DES/RC considered unsafe.• Rijndael is the most commonly used.

Page 23: A Developers Guide to Encryption

Deriving keys from passwords

• RFC2898 derives a key and IV from a password and a salt

private static void GetKeyAndIVFromPasswordAndSalt( string password, byte[] salt, SymmetricAlgorithm symmetricAlgorithm, ref byte[] key, ref byte[] iv){ Rfc2898DeriveBytes rfc2898DeriveBytes = new Rfc2898DeriveBytes(password, salt); key = rfc2898DeriveBytes.GetBytes( symmetricAlgorithm.KeySize / 8); iv = rfc2898DeriveBytes.GetBytes( symmetricAlgorithm.BlockSize / 8);}

Page 24: A Developers Guide to Encryption

Message Authentication Codes

• MACs provide data integrity.

• A checksum of the plaintext combined with a MAC key.

• MAC can be stored alongside data, key cannot.

Page 25: A Developers Guide to Encryption

Demo Time!

Page 26: A Developers Guide to Encryption

Generating a MACprivate static byte[] CalculateMAC( byte[] plainText, byte[] key){ HMACSHA256 hmac = new HMACSHA256(key); return hmac.ComputeHash(plainText);}

Page 27: A Developers Guide to Encryption

Asymmetric Encryption

• Two keys are used.• A public key allows

encryption.• A private key allows

decryption.• Slow, computationally

heavy.• Only for small amounts

of data.

Page 28: A Developers Guide to Encryption

Demo Time!

Page 29: A Developers Guide to Encryption

Encrypting AsymmetricallyRSACryptoServiceProvider rsa = new RSACryptoServiceProvider(1024);string publicKey = rsa.ToXmlString(false);string privateKey = rsa.ToXmlString(true);…RSACryptoServiceProvider rsa = new RSACryptoServiceProvider(); rsa.FromXmlString(publicKey);byte[] ciphertextAsBytes = rsa.Encrypt(plaintextAsBytes, true);

Page 30: A Developers Guide to Encryption

Encrypting AsymmetricallyRSACryptoServiceProvider rsa = new RSACryptoServiceProvider(1024);string publicKey = rsa.ToXmlString(false);string privateKey = rsa.ToXmlString(true);…RSACryptoServiceProvider rsa = new RSACryptoServiceProvider(); rsa.FromXmlString(privateKey);byte[] plaintextAsBytes = rsa.Decrypt(ciphertextAsBytes, true);

Page 31: A Developers Guide to Encryption

X509 Certificate Encryption

• Certificates are a container for a public and private key.

• HTTPS certificate properties show the public key.

• Windows has a secure certificate store.

• Private keys have ACLs.Allow access via Certificate MMC snap-in

Page 32: A Developers Guide to Encryption

Demo Time!

Page 33: A Developers Guide to Encryption

Making Certificates with makecertmakecert -sv devReedRootCA.pvk -r -n "CN=Development Root CA" devRootCA.cer

makecert -pe -n "CN=barryd" -a sha1 -sky exchange -eku 1.3.6.1.5.5.7.3.1 -ic devReedRootCA.cer -iv devRootCA.pvk -sp "Microsoft RSA SChannel Cryptographic Provider" -sy 12 -sv barryd.pvk barryd.cer

pvk2pfx -pvk barryd.pvk -spc barryd.cer -pfx barryd.pfx

Page 34: A Developers Guide to Encryption

Loading a Certificatestatic X509Certificate2 LoadCertificate(string serialNumber){ X509Store certificateStore = new X509Store(StoreName.My,

StoreLocation.CurrentUser); certificateStore.Open(OpenFlags.ReadOnly); X509Certificate2Collection searchResults = certificateStore.Certificates.Find( X509FindType.FindBySerialNumber, serialNumber, false);

if (searchResults.Count != 1) { throw new ArgumentException( "Cannot find individual certificate with the serial # specified.", "serialNumber"); }

certificateStore.Close(); return searchResults[0];}

Page 35: A Developers Guide to Encryption

Encrypting With A CertificateX509Certificate2 certificate = LoadCertificate(this.serialNumber.Text);

RSACryptoServiceProvider encryptionProvider = (RSACryptoServiceProvider) certificate.PublicKey.Key;

byte[] cipherText = encryptionProvider.Encrypt( plaintextAsBytes, true));

Page 36: A Developers Guide to Encryption

Decrypting With A CertificateX509Certificate2 certificate = LoadCertificate(this.serialNumber.Text);

if (!certificate.HasPrivateKey) throw new CryptographicException( "No private key.");

RSACryptoServiceProvider encryptionProvider = (RSACryptoServiceProvider) certificate;

byte[] plaintext = encryptionProvider.Decrypt( ciphertextAsBytes, true));

Page 37: A Developers Guide to Encryption

Envelopes & Signing with certificates

• Signing guarantees data integrity.

• Signing with a certificate provides non-repudiation.

• CMS / PKCS #7 is the standard envelope format.

Page 38: A Developers Guide to Encryption

Encrypting a CMS envelopestatic byte[] EncryptForCertificate( byte[] plaintext, X509Certificate2 certificate){ ContentInfo contentInfo = new ContentInfo(plaintext); EnvelopedCms envelopedCms = new EnvelopedCms(contentInfo);

CmsRecipient recipient = new CmsRecipient(certificate); envelopedCms.Encrypt(recipient); return envelopedCms.Encode();}

Page 39: A Developers Guide to Encryption

Signing a CMS envelopestatic byte[] SignWithCertificate( byte[] plaintext, X509Certificate2 certificate){ ContentInfo contentInfo = new ContentInfo(plaintext); CmsSigner signer = new CmsSigner(certificate); SignedCms signedCms = new SignedCms(contentInfo); signedCms.ComputeSignature(signer); return signedCms.Encode();}

Page 40: A Developers Guide to Encryption

Decrypting a CMS envelopestatic byte[] DecryptEnvelopedCMS( byte[] envelopeAsBytes){ EnvelopedCms envelopedCms = new EnvelopedCms(); envelopedCms.Decode(envelopeAsBytes); envelopedCms.Decrypt(); return envelopedCms.ContentInfo.Content;}

Page 41: A Developers Guide to Encryption

Validating X509 Signaturesstatic bool IsSignatureValid(SignedCms signedCms){ bool result = false; try { // Call with true to check CRLs. signedCms.CheckSignature(false); foreach (SignerInfo signerInfo in signedMessage.SignerInfos) { X509Certificate2 signingCert = signerInfo.Certificate; // Validate signingCert is known. } result = true; } catch (CryptographicException) { } return result;}

Page 42: A Developers Guide to Encryption

Encrypting and Signing XML

• XML has standards for Encryption and Signing - XmlEnc & XmlDSig

• Can encrypt and sign multiple elements with multiple keys.

• Typically done with certificates.

• Certificate is used to protect generated symmetric key.

Page 43: A Developers Guide to Encryption

Demo Time!

Page 44: A Developers Guide to Encryption

Encrypting XMLprivate static void EncryptXml( XmlDocument document, string elementIdToEncrypt, X509Certificate2 certificate){ // Extract the element to encrypt XmlElement elementToEncrypt = document.GetElementsByTagName(elementIdToEncrypt)[0] as XmlElement; if (elementToEncrypt == null) { throw new XmlException("The specified element was not found"); } // Create an instance of the encryptedXml class, // and encrypt the data EncryptedXml encryptedXml = new EncryptedXml(); EncryptedData encryptedData = encryptedXml.Encrypt(elementToEncrypt, certificate); // Replace the original element. EncryptedXml.ReplaceElement(elementToEncrypt, encryptedData, false);}

Page 45: A Developers Guide to Encryption

Decrypting XMLprivate static void DecryptXml( XmlDocument document){ // Create a new EncryptedXml object // from the document EncryptedXml encryptedXml = new EncryptedXml(document); // Decrypt the document. encryptedXml.DecryptDocument();}

Page 46: A Developers Guide to Encryption

Signing XMLprivate static void SignXml(XmlDocument document, X509Certificate2 certificate){ SignedXml signedXml = new SignedXml(document) { SigningKey = certificate.PrivateKey }; Reference reference = new Reference { Uri = string.Empty }; XmlDsigC14NTransform transform = new XmlDsigC14NTransform(); reference.AddTransform(transform); XmlDsigEnvelopedSignatureTransform envelope = new XmlDsigEnvelopedSignatureTransform(); reference.AddTransform(envelope); signedXml.AddReference(reference); KeyInfo keyInfo = new KeyInfo(); keyInfo.AddClause(new KeyInfoX509Data(certificate)); signedXml.KeyInfo = keyInfo; signedXml.ComputeSignature(); XmlElement xmlDigitalSignature = signedXml.GetXml(); document.DocumentElement.AppendChild(document.ImportNode(xmlDigitalSignature, true));}

Page 47: A Developers Guide to Encryption

Validating XML Signaturesprivate static bool VerifySignature(XmlDocument document){ SignedXml signedXml = new SignedXml(document);

XmlNodeList nodeList = document.GetElementsByTagName("Signature"); if (nodeList.Count <= 0) { throw new CryptographicException("No signature found."); } signedXml.LoadXml((XmlElement)nodeList[0]); return signedXml.CheckSignature();}

Page 48: A Developers Guide to Encryption

Extracting the signing certificateprivate static bool VerifySignature(XmlDocument document, out X509Certificate signingCertificate){ SignedXml signedXml = new SignedXml(document);

XmlNodeList nodeList = document.GetElementsByTagName("Signature"); if (nodeList.Count <= 0) throw new CryptographicException("No signature found.");

signedXml.LoadXml((XmlElement)nodeList[0]);

signingCertificate = null; foreach (KeyInfoClause keyInfoClause in signedXml.KeyInfo) { if (!(keyInfoClause is KeyInfoX509Data)) continue;

KeyInfoX509Data keyInfoX509Data = keyInfoClause as KeyInfoX509Data; if ((keyInfoX509Data.Certificates != null) && (keyInfoX509Data.Certificates.Count == 1)) signingCertificate = (X509Certificate)keyInfoX509Data.Certificates[0]; } return signedXml.CheckSignature();}

Page 49: A Developers Guide to Encryption

Links

• http://www.keylength.com/ - collection of recommended algorithms, key lengths and expiries.

• http://csrc.nist.gov/groups/ST/toolkit/ - US National Institute of Standards and Technology recommendations

Page 50: A Developers Guide to Encryption

Buy my book

Beginning ASP.NET SecurityWrox PressISBN: 978-0470743652Available now!

An ideal valentine’s gift for your loved one …