Cryptography & X.509
Certificates
Dominick Baier
• Solution architect and security consultant at thinktecture
• Focus on
– security in distributed applications – identity management
– Windows/.NET security – cloud computing
• Microsoft MVP for Developer Security
• http://www.leastprivilege.com
Agenda
• Why cryptography?
• Symmetric cryptography
• Asymmetric cryptography
• X.509 certificates & public key cryptography standards
Why cryptography?
• Confidentiality, Integrity, Authenticity
History: symmetric cryptography
Encryption
Symmetric crypto in the .NET Framework
• Cryptography consists of two primitives
• Hashing
– integrity protection • Encryption
Hash algorithms
MD5 SHA1 RIPEMD160 MD5CryptoServiceProvider RIPEMD160Managed SHA1Managed SHA256 SHA384 SHA256Managed SHA384Managed SHA1CryptoServiceProvider HashAlgorithmCreating a hash
void SimpleHash() {
string data = “some data";
byte[] dataBytes = Encoding.Unicode.GetBytes(data);
HashAlgorithm sha = new SHA1Managed();
byte[] hashBytes = sha.ComputeHash(dataBytes);
string hashString = Convert.ToBase64String(hashBytes); }
Stream Ciphers
• How a stream cipher works
– key is used as a seed for a pseudo-random-number generator – run the PRNG continuously to get a key stream
– XOR each bit of plaintext with corresponding bit in key stream – most common example is RC4
• Benefits
– easy to implement, blazingly fast
– ciphertext is always exactly the same length as plaintext • Drawbacks
– incredibly easy to misuse
Block Ciphers
• How a block cipher works
– input is broken up into fixed size blocks (typically 8- or 16-bytes) – transformation f() applied to key, result xor‟d into block
– this is known as a “round” – 16 to 32 rounds is typical
f()
f()
xor
Round 1
Round N
key
plaintext block
xor
Encrypting data in .NET
• Setting up
– choose an algorithm and implementation – choose a feedback mode
– choose a padding mode
– generate an initialization vector (IV) – choose a key
• Encrypting
– record the initialization vector for use during decryption – create a CryptoStream object based on your key
Algorithms and implementations in .NET
SymmetricAlgorithm DES RC2 Rijndael TripleDES DESCryptoServiceProvider RC2CryptoServiceProvider RijndaelManaged TripleDESCryptoServiceProviderExample: encrypting a file
void Encrypt(FileStream s, FileStream d) {
SymmetricAlgorithm alg = new RijndaelManaged(); alg.Mode = CipherMode.CBC;
alg.Padding = PaddingMode.PKCS7; alg.GenerateIV();
_writeIV(alg, d); // writes alg.IV to the stream
// this example uses a password as a key
// more on this later...
alg.Key = _keyFromPassword(_getPassword()); Stream cryptOutput = new CryptoStream(d, alg.CreateEncryptor(),
CryptoStreamMode.Write); _pump(s, cryptOutput);
Decrypting data in .NET
• Setting up
– choose the same algorithm you used to encrypt (duh!) – choose the same feedback mode
– choose the same padding mode
– retrieve the initialization vector (IV) used during encryption – retrieve the key
• Decrypting
– create a CryptoStream object based on your key – pump data through the stream to decrypt it
– close the CryptoStream immediately when done decrypting – this causes it to eat any leftover padding from the input stream
Example: decrypting a file
void Decrypt(FileStream s, FileStream d) {
SymmetricAlgorithm alg = new RijndaelManaged(); alg.Mode = CipherMode.CBC;
alg.Padding = PaddingMode.PKCS7; _readIV(alg, s);
alg.Key = _keyFromPassword(_getPassword()); Stream cryptOutput = new CryptoStream(d, alg.CreateDecryptor(),
CryptoStreamMode.Write); _pump(s, cryptOutput);
cryptOutput.Close(); }
Passwords as keys
• Passwords or phrases can be turned into conventional keys
– variable length passphrase converted into a fixed length key – hash of password produces fixed length key
• Passwords are often long term secrets
– we limit their use as much as possible to avoid compromise – shorter term secrets known as session keys are often used – long term secrets such as passwords are usually used to help
exchange short term secrets such as session keys
• Use short term keys to encrypt data whenever possible
Turning a password into a key
static byte[] keyFromPassword(string password) {
const int KEY_SIZE = 16;
PasswordDeriveBytes pdb = new PasswordDeriveBytes(password, null);
byte[] key = pdb.GetBytes(KEY_SIZE); return key;
Reality check – password entropy
• The code you just saw has a huge flaw
– it accepts passwords of arbitrary quality – it always produces a 128-bit key
– it gives the illusion that you have the protection of a 128-bit key • A password that truly has 128-bits of entropy is rare indeed
– this requires 20 random characters from the following: • upper and lower case alpha (A-Z, a-z)
• digits (0-9) • punctuation
• Be sure to give the user feedback on password quality!
Calculating the entropy of a password
static double _passwordEntropy(string s) {
if (0 == s.Length) return 0;
// first determine the type of characters used
int permutations = 0;
// psuedo-code for brevity
if (usesLowerCaseAlpha) permutations += 26; if (usesUpperCaseAlpha) permutations += 26; if (usesNumerics) permutations += 10; if (usesPunctuation) permutations += 32; double passwordEntropy =
Math.Log10(Math.Pow(permutations, s.Length)) / Math.Log10(2);
return passwordEntropy; }
History: asymmetric cryptography
Alice
Bob
Problem solved?
• Not really…
– public key cryptography is too slow to handle large data – initial key exchange prone to Man-in-the-Middle attacks
symmetric (session) key asymmetric key
History: X509 certificates
History: X509 certificates
• ASN.1 encoded file containing
– public key
– additional information about owner and issuer – expiration and purpose information
– revocation information
– digital signature to prevent manipulation • All problems solved?
– how to bootstrap trust?
Solution (or at least where we are currently)
• X.509 certificates provide „authentication“ for public keys
• Public keys used to securely transmit session key
• Session key used to encrypt/sign bulk data
symmetric (session) key asymmetric key X.509 certificate
Example: SSL
connect
send certificate
generate session key & encrypt with public key CRL
How to get a certificate
• Depends on how you can bootstrap trust
• Public facing applications
– typically buy a certificate from a company that is already trusted (Verisign, TrustCenter etc..)
• Intranet applications
– often internal CA/PKI • Test/Development
– internal PKI
– test/development CA – makecert.exe
Makecert.exe
• Command line tool to generate certificates & private keys
makecert
-r
-n "CN=TestCertificate"
-a sha1
-sv TestCert.pvk
TestCert.cer
// self signed
// name
// sig. algo
// priv. Key
// certificate
Makecert.exe – creating a test root
• Can be used to sign leaf certificates
makecert
-r
-n "CN=Test Root Authority"
-a sha1
-sky signature
-sv TestRoot.pvk
TestRoot.cer
// self signed
// subject name
// sig. algo.
// use for sig.
// private key
// certificate
Makecert.exe – creating issued certificates
• Can be used to sign leaf certificates
makecert
-n "CN=TestCert"
-a sha1
-sky exchange
-sv TestCert.pvk
-iv TestRoot.pvk
-ic TestRoot.cer
TestCert.cer
// subject name
// sig. algo.
// use for ex.
// private key
// root priv key
// root certificate
// certificate
Windows Certificate Services
The Windows Certificate Store
• Abstraction of physical storage of certificates / private keys
– hard disk, smart card, hardware storage module – unified API
The Windows Certificate Store
• Computer store
– machine wide certificates
– trusted root certification authorities
– private keys are ACL„ed for Administrators and SYSTEM • User store
– one store per (user) account – stored in account profile
– only accessible to the corresponding user
Using the certificate store
• Importing certificates
– makecert.exe & certificate services allow deployment directly to the certificate store
– import .cer & .pfx (or .p12) files • pvk2pfx.exe
• certutil.exe & winhttpcertcfg.exe • API
• Accessing certificates
– MMC snap-in
– System.Security.Cryptography.X509Certificates • X509Store & X509Certificate2 class
Common gotcha: ACLs
• Certificates (& private keys) must be deployed to the store of the corresponding user
• Some hosting environments don‘t load the user profile
– IIS <7
– in this case keys must be deployed to machine store – private key must be explicitly ACL„ed for worker account
• „keyset does not exist“
• How?
– certificates MMC Vista+ – winhttpcertcfg.exe
Certificate specific APIs
• System.Security.Cryptography.X509Certificates
– X509Store, X509Certificate2, X509Chain
• System.Security.Cryptography.PKCS
– implementation of PKCS#7 CMS standard
– digital signatures & encryption for arbitrary data – interoperable
Typical use of the certificate store
Typical use of the certificate store
UI helpers
• Standard Windows dialogs
Overview of PKCS#7 support in .NET
ContentInfo
SignedCms
EnvelopedCms
Example: signing data
byte[] sign(byte[] input, X509Certificate2 certificate) {
// what is signed
ContentInfo content = new ContentInfo(input); // who signs
CmsSigner signer = new CmsSigner(certificate);
// represents a signed message
SignedCms signedMessage = new SignedCms(content);
// sign the message
signedMessage.ComputeSignature(signer); // serialize the message
return signedMessage.Encode(); }
What we just produced
plaintext message
signer Cert issuer Cert serial number
hash of message encrypted with the private key of signer
Example: encryption using certificates
byte[] encrypt(X509Certificate2 cert, byte[] input) {
// what is encrypted
ContentInfo contentInfo = new ContentInfo(input);
EnvelopedCms envelopedMessage = new EnvelopedCms(contentInfo);
// who can decrypt
CmsRecipient recipient = new CmsRecipient(cert);
// encrypt message
envelopedMessage.Encrypt(recipient);
// serialize the message
return envelopedMessage.Encode(); }
What we just produced
(signed) data
encrypted
with session key
recipient Cert issuer Cert serial number
session key encrypted with the public key of recipient
Decrypting an enveloped message
static byte[] Decrypt(byte[] data) {
// create EnvelopedCms and deserialize
EnvelopedCms encryptedMessage = new EnvelopedCms();
encryptedMessage.Decode(data); // decrypt
encryptedMessage.Decrypt(); // return plain text
return encryptedMessage.ContentInfo.Content; }
Verifying the signature
void checkSignature(SignedCms signedMessage) {
// true checks signature only
signedMessage.CheckSignature(true);
foreach (SignerInfo signerInfo in signedMessage.SignerInfos) {
// access the certificate
X509Certificate2 cert = signerInfo.Certificate; }
Verifying certificates
• Just because the signature matches the public key doesn’t mean it’s a valid signature
– you need to check the validity of the certificate itself – this means looking all the way up the chain of trust – this means looking for revoked certificates
• Certificate Revocation Lists (CRL) are important
– authorities that issue certificates also publish CRLs regularly – .NET allows you to check against CRLs, but it‟s not automatic
Example: verifying a certificate
void VerifyCert(X509Certificate2 cert) {
// set up verification policy
X509Chain chain = new X509Chain();
chain.ChainPolicy.RevocationMode = X509RevocationMode.Online | X509RevocationMode.Offline; chain.ChainPolicy.RevocationFlag = X509RevocationFlag.EntireChain; chain.ChainPolicy.UrlRetrievalTimeout = new TimeSpan(5000);
chain.ChainPolicy.VerificationTime = DateTime.Now;
// verify certificate
if (!chain.Build(cert)) {
// iterate through error information
foreach (X509ChainElement e in chain.ChainElements) {
.NET APIs that use
X509Certificate2
• System.Net.HttpWebRequest
– whenever https:// is used
– ServicePointManager to control behavior
• System.Net.Security.SslStream
– implements SSL over arbitrary stream for clients and servers
• System.Web.HttpRequest
– access to SSL client certificates
• System.Net.Mail.SmtpClient – SMTP over SSL support • System.Security.Cryptography.Xml.* – W3C signed/encrypted XML • System.ServiceModel.* – e.g. WS-Security
Summary
• .NET has full featured crypto support
• Certificates are everywhere
• It is a complex topic, but as a developer you typically care about
– the certificate store (and ACLs) – trust chain
– CRL list
– expiration date
Resources
• How to build a test/dev CA
– http://www.leastprivilege.com/HowToBuildADevelopmentTestDemoCA.aspx • Makecert.exe – http://msdn.microsoft.com/en-us/library/bfsktky3(VS.71).aspx • CertUtil.exe – http://technet.microsoft.com/en-us/library/cc732443(WS.10).aspx • Pvk2Pfx.exe – http://msdn.microsoft.com/en-us/library/dd434714.aspx • WinHttpCertCfg.exe – http://www.microsoft.com/downloads/details.aspx?familyid=c42e27ac-3409-40e9-8667-c748e422833f&displaylang=en
• How to get to a private key file programmatically
– http://www.leastprivilege.com/HowToGetToThePrivateKeyFileFromA Certificate.aspx