A Developers Guide to Encryption - idunno.org

conversebazaarΛογισμικό & κατασκευή λογ/κού

2 Νοε 2013 (πριν από 4 χρόνια και 7 μέρες)

118 εμφανίσεις

A Developer’s Guide to Encryption

Barry Dorrans

MVP


Developer Security

(well for 9 more days anyway)

barryd@idunno.org

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

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
.

Definitions


Plaintext /
Cleartext




Unencrypted Data.


Ciphertext



Encrypted Data.


Cipher


Encryption algorithm.

Random Numbers


Cryptography needs
random numbers.


Random isn’t really
random.


PRNG


Pseudo
Random Number
Generator.


𝑥
𝑛
+
1
=
𝑋
𝑛
+

mod

𝑚


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
;

}

Hardware RNGs


Based on


Radioactive decay,


Background noise,


Other entropy source.


Specialised Hardware.


But now even Intel
Chipsets have hardware
RNGs.


(Post Office Ernie)

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.

Generating a hash

HashAlgorithm

algorithm =


new
SHA256Managed();

byte[] hash =


algorithm.ComputeHash
(plaintext);

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.

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.

Salting a hash

HashAlgorithm

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
);

Comparing byte arrays

public
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;

}

Demo Time!

Encryption Keys


Once you lose them
change the “locks
”.


Keys are like condoms
-

don’t reuse them.

Symmetric Encryption


A single key is used for
encryption and
decryption.


Fast, computationally
cheap.


Needs a shared key.


Repudiable
.

Symmetric Keys


Keys are
cryptographically secure
random data.


Size of key depends on
algorithm.

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

Demo Time!

Encrypting Symmetrically

RijndaelManaged

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
();

Decrypting Symmetrically

RijndaelManaged

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
();

Symmetric Encryption Algorithms


DES


TripleDES


Rivest

Cipher 2


Rijndael
/AES



DES/RC considered unsafe.


Rijndael

is the most commonly used.

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);

}

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.

Demo Time!

Generating a MAC

private
static byte[]
CalculateMAC
(


byte
[]
plainText
,


byte
[] key)

{


HMACSHA256
hmac

=


new
HMACSHA256(key);


return
hmac.ComputeHash
(
plainText
);

}

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.


Demo Time!

Encrypting Asymmetrically

RSACryptoServiceProvider

rsa



=
new
RSACryptoServiceProvider
(1024);

s
tring
publicKey

=


rsa.ToXmlString
(false);

string
privateKey

=


rsa.ToXmlString
(true);



RSACryptoServiceProvider

rsa

=


new
RSACryptoServiceProvider
();
rsa.FromXmlString
(
publicKey
);

byte[]
ciphertextAsBytes

=


rsa.Encrypt
(
plaintextAsBytes
,
true);


Encrypting Asymmetrically

RSACryptoServiceProvider

rsa



=
new
RSACryptoServiceProvider
(1024);

s
tring
publicKey

=


rsa.ToXmlString
(false);

string
privateKey

=


rsa.ToXmlString
(true);



RSACryptoServiceProvider

rsa

=


new
RSACryptoServiceProvider
();
rsa.FromXmlString
(
privateKey
);

byte[]
plaintextAsBytes

=


rsa.Decrypt
(
ciphertextAsBytes
,
true);


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

Demo Time!

Making Certificates with
makecert

makecert

-
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

Loading a Certificate

static
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];

}

Encrypting With A Certificate

X509Certificate2
certificate =


LoadCertificate
(
this.serialNumber.Text
);


RSACryptoServiceProvider



encryptionProvider

=


(
RSACryptoServiceProvider
)


certificate.PublicKey.Key
;


byte[]
cipherText

=



encryptionProvider.Encrypt
(


plaintextAsBytes
,
true
));

Decrypting With A Certificate

X509Certificate2 certificate =


LoadCertificate
(
this.serialNumber.Text
);


if
(!
certificate.HasPrivateKey
)


throw
new
CryptographicException
(


"No private key.");


RSACryptoServiceProvider



encryptionProvider

=


(
RSACryptoServiceProvider
)


certificate;


byte[]
plaintext
=


encryptionProvider.Decrypt
(


ciphertextAsBytes
, true));

Envelopes & Signing with certificates


Signing guarantees data
integrity.


Signing with a
certificate provides
non
-
repudiation.


CMS / PKCS #7 is the
standard envelope
format.

Encrypting a CMS envelope

static 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
();

}

Signing a CMS envelope

s
tatic 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
();

}

Decrypting a CMS envelope

s
tatic byte[]
DecryptEnvelopedCMS
(


byte[]
envelopeAsBytes
)

{



EnvelopedCms

envelopedCms

=



new
EnvelopedCms
();



envelopedCms.Decode
(
envelopeAsBytes
);



envelopedCms.Decrypt
();






return
envelopedCms.ContentInfo.Content
;

}

Validating X509 Signatures

s
tatic 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;

}

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.

Demo Time!

Encrypting XML

private 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);

}

Decrypting XML

private static void
DecryptXml
(


XmlDocument

document)

{


//
Create a new
EncryptedXml

object


// from
the document


EncryptedXml

encryptedXml

=


new
EncryptedXml
(document);




// Decrypt the document.


encryptedXml.DecryptDocument
();

}

Signing XML

private
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));

}

Validating XML Signatures

private
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
();

}

Extracting the signing certificate

private 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
();

}

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

Buy my book

Beginning ASP.NET Security

Wrox Press

ISBN: 978
-
0470743652

Available now!


An ideal valentine’s gift for
your loved one …