
RSA Highlights
- The plaintext‘s length must be less than or equal to the modulus’s size minus 88-bit padding, while OAEP padding typically adds 42 bytes. (1960 bits at most, given a 2048-bit modulus)
- The ciphertext’s length equals the modulus’s size (p x q). (A 128-bit plaintext generates a 2048-bit ciphertext, given a 2048-bit modulus)
- Because the size of hash values and symmetric keys is typically less than 512 bits, asymmetric cryptography is suitable for key exchange and digital signatures.
- However, because of the lack of forward secrecy support, RSA nowadays is deemed inappropriate for key exchange.
- “Forward secrecy (FS), also known as perfect forward secrecy (PFS), is a feature of specific key-agreement protocols that gives assurances that session keys will not be compromised even if long-term secrets used in the session key exchange are compromised.” (Wikipedia)
PKCS #1
RSAPublicKey ::= SEQUENCE {
modulus INTEGER, -- n
publicExponent INTEGER -- e
}
RSAPrivateKey ::= SEQUENCE {
version Version,
modulus INTEGER, -- n
publicExponent INTEGER, -- e
privateExponent INTEGER, -- d
prime1 INTEGER, -- p
prime2 INTEGER, -- q
exponent1 INTEGER, -- d mod (p-1)
exponent2 INTEGER, -- d mod (q-1)
coefficient INTEGER, -- (inverse of q) mod p
otherPrimeInfos OtherPrimeInfos OPTIONAL
}
Sample Code
The following is a snippet of C# code in LINQPad that demonstrates RSA Cryptography:
System
System.Security.Cryptography
void Main()
{
string message =
"0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF"+
"0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF"+
"0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF"+
"0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF01234";
(message.Length * 8).Dump("message.Length"); //1960 bits
RSAParameters key = RsaEncryption.GenerateKey(2048);
key.Dump("Key per PKCS #1");
var encryptedData = RsaEncryption.Encrypt(message, key);
(encryptedData.Length * 8).Dump("encryptedData.Length");
var decryptedData = RsaEncryption.Decrypt(encryptedData, key);
(decryptedData.Length * 8).Dump("decryptedData.Length");
/*
string encryptedMessage = Convert.ToBase64String(encryptedData);
string decryptedMessage = Encoding.UTF8.GetString(RsaEncryption.Decrypt(encryptedData, key));
Console.WriteLine("Encrypted message: " + encryptedMessage);
Console.WriteLine("Decrypted message: " + decryptedMessage);
*/
//Digital Signature
var hash = Sha256Hash.ComputeHash(message);
BitConverter.ToString(hash).Dump("hash");
(hash.Length * 8).Dump("hash.Length");
var signature = DigitalSignature.Sign(hash, key);
bool verified = DigitalSignature.Verify(hash, signature, key);
(signature.Length * 8).Dump("signature.Length");
verified.Dump("verified");
//Console.WriteLine("Signature: " + signature);
//Console.WriteLine("Verified: " + verified);
}
// Define other methods and classes here
public class Sha256Hash
{
public static byte[] ComputeHash(string message)
{
byte[] hashValue;
using (SHA256 sha256 = SHA256.Create())
{
hashValue = sha256.ComputeHash(Encoding.UTF8.GetBytes(message));
}
return hashValue;
}
}
public class RsaEncryption
{
public static byte[] Encrypt(string message, RSAParameters key)
{
byte[] encryptedData;
using (RSACryptoServiceProvider rsa = new RSACryptoServiceProvider())
{
rsa.ImportParameters(key);
encryptedData = rsa.Encrypt(Encoding.UTF8.GetBytes(message), false);
}
return encryptedData;
}
public static byte[] Decrypt(byte[] ciphertext, RSAParameters key)
{
byte[] decryptedData;
using (RSACryptoServiceProvider rsa = new RSACryptoServiceProvider())
{
rsa.ImportParameters(key);
decryptedData = rsa.Decrypt(ciphertext, false);
}
return decryptedData;
}
public static RSAParameters GenerateKey(int keySzie)
{
RSACryptoServiceProvider rsa = new RSACryptoServiceProvider(keySzie);
return rsa.ExportParameters(true);
}
}
public class DigitalSignature
{
public static byte[] Sign(byte[] hash, RSAParameters key)
{
byte[] signature;
using (RSACryptoServiceProvider rsa = new RSACryptoServiceProvider())
{
rsa.ImportParameters(key);
signature = rsa.SignHash(hash, CryptoConfig.MapNameToOID("SHA256"));
}
return signature;
}
public static bool Verify(byte[] hash, byte[] signature, RSAParameters key)
{
using (RSACryptoServiceProvider rsa = new RSACryptoServiceProvider())
{
rsa.ImportParameters(key);
return rsa.VerifyHash(hash, CryptoConfig.MapNameToOID("SHA256"), signature);
}
}
}