Protecting Your Most Precious of Secrets … Meet PBE

--

And, so you have an RSA key pair which you use to sign your software or to protect your symmetric keys. For an intruder, this is one of the most valuable things they can gain, as they will also be able to sign for your software and decrypt your symmetric keys. One of the most popular ways of protecting the private key is to use PBE (Password-Based Encryption), which takes a low entropy password and encrypts the private key. One of the most popular methods for this is PBKDF2, and which slows down the generation of the encryption key.

In this case, though, we will use the methods provided with Bouncy Castle, and aim to protect an RSA private key using the Bouncy Castle library. First, we can generate a random RSA key pair with:


RsaKeyPairGenerator pGen = new RsaKeyPairGenerator();

pGen.Init(new KeyGenerationParameters(new SecureRandom(), s));

AsymmetricCipherKeyPair pair = pGen.GenerateKeyPair();

Next, we can encrypt the private key using a defined password (msg) defined method, a salt value (nonce), and with a number of rounds:

var encKey  = PrivateKeyFactory.EncryptKey(method, msg.ToCharArray(),nonce,
1, pair.Private);

Finally, we can decrypt the private key when we want it back:

var decKey  = PrivateKeyFactory.DecryptKey( msg.ToCharArray(),encKey);

For Bouncy Castle, the methods of encryption we can use include PBEwithMD2andDES-CBC, PBEwithMD2andRC2-CBC, PBEwithMD5andDES-CBC, PBEwithMD5andRC2-CBC,
PBEwithSHA1andDES-CBC, PBEwithSHA1andRC2-CBC, PBEwithSHA-1and128bitRC4, PBEwithSHA-1and40bitRC4,
PBEwithSHA-1and3-keyDESEDE-CBC, PBEwithSHA-1and2-keyDESEDE-CBC, PBEwithSHA-1and128bitRC2-CBC, and PBEwithSHA-1and40bitRC2-CBC. With PBEwithMD2andDES-CBC, for example, we hash with MD2 and then encrypt with DES-CBC.

Now, let’s code this with [here]:



namespace PBE
{

using Org.BouncyCastle.Crypto;
using Org.BouncyCastle.Crypto.Generators;
using Org.BouncyCastle.Crypto.Parameters;

using Org.BouncyCastle.Security;

class Program
{

static void Main(string[] args)
{



var msg="Hello";
var iv="00112233445566778899AABBCCDDEEFF00";
var s=64;
var method="PBEwithSHA1andDES-CBC";

if (args.Length >0) msg=args[0];
if (args.Length >1) iv=args[1];
if (args.Length >2) s=Convert.ToInt32(args[2]);
if (args.Length >3) method=args[3];

byte[] nonce = new byte[16];
Array.Copy(Convert.FromHexString(iv), nonce, 16);


try {


RsaKeyPairGenerator pGen = new RsaKeyPairGenerator();

pGen.Init(new KeyGenerationParameters(new SecureRandom(), s));

AsymmetricCipherKeyPair pair = pGen.GenerateKeyPair();



var encKey = PrivateKeyFactory.EncryptKey(method, msg.ToCharArray(),nonce, 1, pair.Private);

var decKey = PrivateKeyFactory.DecryptKey( msg.ToCharArray(),encKey);


Console.WriteLine("Password:\t{0}",msg);
Console.WriteLine("Salt:\t\t{0}",iv);
Console.WriteLine("Method:\t{0}",method);
Console.WriteLine("\nEncrypted private key: {0}",Convert.ToBase64String(encKey));
Console.WriteLine("Encrypted private key: {0}",Convert.ToHexString(encKey));


RsaPrivateCrtKeyParameters before = ((RsaPrivateCrtKeyParameters)pair.Private);
RsaPrivateCrtKeyParameters after = ((RsaPrivateCrtKeyParameters)decKey);

Console.WriteLine("\nPrivate key P:\t\t\t{0}",before.P);
Console.WriteLine("Decrypted private key P:\t{0}",after.P);

Console.WriteLine("Private key P:\t\t\t{0}",before.Q);
Console.WriteLine("Decrypted private key P:\t{0}",after.Q);
Console.WriteLine("Private key d:\t\t\t{0}",before.Modulus);
Console.WriteLine("Decrypted private key d:\t{0}",after.Modulus);
Console.WriteLine("Private key d:\t\t\t{0}",before.Exponent);
Console.WriteLine("Decrypted private key d:\t{0}",after.Exponent);
Console.WriteLine("Private key e:\t\t\t{0}",before.PublicExponent);
Console.WriteLine("Decrypted private key e:\t{0}",after.PublicExponent);


} catch (Exception e) {
Console.WriteLine("Error: {0}",e.Message);
}
}
}



}

And then we can show that the decrypted key is the same as the key generated with samples runs. With PBEwithMD2andDES-CBC and with a 64-bit RSA key we get [here]:

Password: Hello World!
Salt: 00112233445566778899AABBCCDDEEFF00
Method: PBEwithSHA-1and3-keyDESEDE-CBC

Encrypted private key: MH8wIwYKKoZIhvcNAQwBAzAVBBAAESIzRFVmd4iZqrvM3e7/AgEBBFidOX7Jwc+2UyDO+nFDZw+ny4MTc0EN4Eb7HmPpNyx79zZ4CWKMgivkG/4sjCKnR+2QpIueAO+wC+8lAIi8RXJOE1VkxV9zJIjIWfgVc4qVVAXph/WI9ht7
Encrypted private key: 307F3023060A2A864886F70D010C01033015041000112233445566778899AABBCCDDEEFF02010104589D397EC9C1CFB65320CEFA7143670FA7CB831373410DE046FB1E63E9372C7BF7367809628C822BE41BFE2C8C22A747ED90A48B9E00EFB00BEF250088BC45724E135564C55F732488C859F815738A955405E987F588F61B7B

Private key P: 3235731847
Decrypted private key P: 3235731847
Private key P: 2996920249
Decrypted private key P: 2996920249
Private key N: 9697230292608469903
Decrypted private key N: 9697230292608469903
Private key d: 708755864194884833
Decrypted private key d: 708755864194884833
Private key e: 65537
Decrypted private key e: 65537

The public key is (e,N) and the private key is (d,N). We can see that e=65537, d=708755864194884833 and N=9697230292608469903, and where we have recovered each of the values using the password of “Hello World!”. We can then use PBEwithSHA-1and3-keyDESEDE-CBC and a 256-bit RSA key to get [here]:

Password: Hello World!
Salt: 00112233445566778899AABBCCDDEEFF00
Method: PBEwithSHA-1and3-keyDESEDE-CBC

Encrypted private key: MIHwMCMGCiqGSIb3DQEMAQMwFQQQABEiM0RVZneImaq7zN3u/wIBAQSByDnsUGpf3ESKDNbhBy0YMD/7vAwp8DMBiyYoi/WpMdGRnet1/Itf8PwqBLhlP1EEkJv4mNrizT7yr+AdN8lOPUbfAWmUDp5+0SPvqs7/fblfeHLPh8j3BXke5S42BDM4LgRV/0GQwm91rI4dgURYxkFeDECqil8c3qzVr/bNaRmljZQxSFwVNEBnkCPTONRei4b1oZE/byJ0WmRnixfmInbYTLgjFlpbKNPluGMUfcMnPs4XW8oMQwL6DHb/mYCEr5jISiDmC6LA
Encrypted private key: 3081F03023060A2A864886F70D010C01033015041000112233445566778899AABBCCDDEEFF0201010481C839EC506A5FDC448A0CD6E1072D18303FFBBC0C29F033018B26288BF5A931D1919DEB75FC8B5FF0FC2A04B8653F5104909BF898DAE2CD3EF2AFE01D37C94E3D46DF0169940E9E7ED123EFAACEFF7DB95F7872CF87C8F705791EE52E360433382E0455FF4190C26F75AC8E1D814458C6415E0C40AA8A5F1CDEACD5AFF6CD6919A58D9431485C153440679023D338D45E8B86F5A1913F6F22745A64678B17E62276D84CB823165A5B28D3E5B863147DC3273ECE175BCA0C4302FA0C76FF998084AF98C84A20E60BA2C0

Private key P: 316903354222929006607505239513428102251
Decrypted private key P: 316903354222929006607505239513428102251
Private key P: 222792809260785375400273402593360083309
Decrypted private key P: 222792809260785375400273402593360083309
Private key N: 70603788551492125786298011267990832362898971511551990677753325277835130428559
Decrypted private key N: 70603788551492125786298011267990832362898971511551990677753325277835130428559
Private key d: 18117153853097381316632950173090038113398476181828039160558964520393724636473
Decrypted private key d: 18117153853097381316632950173090038113398476181828039160558964520393724636473
Private key e: 65537
Decrypted private key e: 65537

Conclusions

Your private keys are fundamentally important to protect, and PBE is one method we can use to protect these. The strength of the protection will obviously depend on the strength of the password used. Note that storing the private key in an HSM (Hardware Security Module) or to use key wrapping is a much better approach.

--

--

Prof Bill Buchanan OBE FRSE
ASecuritySite: When Bob Met Alice

Professor of Cryptography. Serial innovator. Believer in fairness, justice & freedom. Based in Edinburgh. Old World Breaker. New World Creator. Building trust.