In this case, we will use the methods provided with Bouncy Castle, and aim to protect an ECC private key using the Bouncy Castle library. Typical curves are secp256k1 and NIST P256, and where we protect a value of D, and which is a private key scalar value.
PBE (Password Based Encryption) with ECC private key using Bouncy Castle and C# |
In this case, 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:
X9ECParameters ecParams = ECNamedCurveTable.GetByName(curvename); var curveparam = new ECDomainParameters(ecParams.Curve, ecParams.G, ecParams.N, ecParams.H, ecParams.GetSeed()); Org.BouncyCastle.Crypto.Parameters.ECKeyGenerationParameters keygenParams = new Org.BouncyCastle.Crypto.Parameters.ECKeyGenerationParameters (curveparam, new SecureRandom()); Org.BouncyCastle.Crypto.Generators.ECKeyPairGenerator generator = new Org.BouncyCastle.Crypto.Generators.ECKeyPairGenerator(); generator.Init(keygenParams); var pair = generator.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:
namespace PBE_EC { using Org.BouncyCastle.Asn1.X9; 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 curvename="secp256k1"; var method="PBEwithSHA1andDES-CBC"; if (args.Length >0) msg=args[0]; if (args.Length >1) iv=args[1]; if (args.Length >2) curvename=args[2]; if (args.Length >3) method=args[3]; byte[] nonce = new byte[16]; Array.Copy(Convert.FromHexString(iv), nonce, 16); try { // 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, // PBEwithSHA-1and40bitRC2-CBC, PBEwithHmacSHA-1, PBEwithHmacSHA-224, PBEwithHmacSHA-256, // PBEwithHmacRIPEMD128, PBEwithHmacRIPEMD160, and PBEwithHmacRIPEMD256. X9ECParameters ecParams = ECNamedCurveTable.GetByName(curvename); var curveparam = new ECDomainParameters(ecParams.Curve, ecParams.G, ecParams.N, ecParams.H, ecParams.GetSeed()); Org.BouncyCastle.Crypto.Parameters.ECKeyGenerationParameters keygenParams = new Org.BouncyCastle.Crypto.Parameters.ECKeyGenerationParameters (curveparam, new SecureRandom()); Org.BouncyCastle.Crypto.Generators.ECKeyPairGenerator generator = new Org.BouncyCastle.Crypto.Generators.ECKeyPairGenerator(); generator.Init(keygenParams); var pair = generator.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\t{0}",method); Console.WriteLine("\nEncrypted private key: {0}",Convert.ToBase64String(encKey)); Console.WriteLine("Encrypted private key: {0}",Convert.ToHexString(encKey)); ECPrivateKeyParameters before = ((ECPrivateKeyParameters)pair.Private); ECPrivateKeyParameters after = ((ECPrivateKeyParameters)decKey); Console.WriteLine("Private key D:\t\t\t{0}",before.D); Console.WriteLine("Decrypted private key D:\t{0}",after.D); Console.WriteLine("Private key G:\t\t\t{0}",before.Parameters.G); Console.WriteLine("Decrypted private key G:\t{0}",after.Parameters.G); } catch (Exception e) { Console.WriteLine("Error: {0}",e.Message); } } } }
For the NIST P256 curve with a password of "Hello World!" and encryption of "PBEwithMD2andDES-CBC", we get:
Curve: P-256 Password: Hello World! Salt: 00112233445566778899AABBCCDDEEFF00 Method: PBEwithMD2andDES-CBC Encrypted private key: MIICqDAiBgkqhkiG9w0BBQEwFQQQABEiM0RVZneImaq7zN3u/wIBAQSCAoAZob+YT30lotXL/DiQoHZ1XvE1Qfo5wkliQhSvvuZx86cyTGYJtdU1EiPJQrt0H0NXQGhnZCeEFA/4M99bMd0VykgB1LV0WRxvAnIciGAKyhBcLLzgr0sxs3P+gQVEwmtN6INihl9Yc51CnosO9JyZLqa6Tt3wuSguojRkGb4Co9PR88P0pUFYu9uDmbwjZtj2mXtygkOt8LytaGPWMEgssGpc0Bkib1MUXexr5DUafT7Hp7zvJ2FZa4/hu+YV9SbfvfixeHSrjmdHFnBFOV0ZcTg3/WEHNS+cY1k6VSFbtNQFGKpqaNZHXmR8FCCO57LJk30SxWJaT2LqVuAfsSFhlkrUvDlwL9C+g+3NisJk7s6pmfVxpviiQLVaxCXYIxnllH06wg0sj02h5Xb0oK+R8rYYGRkowpCpx8F/yJhSiQS5ctVCDw0IacEHUcZyxDmnr2eMqTBL7da5hKMCk1i4AuXgIQbJlMtc/9DehTTPsWA60QmVEfogLrl1uCMkmDdW4PeqArSLrwF2moAy14DWg/8B5B+0n8aMMANtLlBVTe5W1z904GZli58/HLJ0i4FKce6q4mU57rmrQhEhyZf8WNM0daVOqP6SGmYFRSJSn2qtvdJeplI7+Otfm0WdGBGbBzS/Si10B9wod+zDSdEJVGt9B4lV6wkbpw2a3aavSwLWP1JsT/iWhu6ttmuWNaxGZexmMIk0lSyBHYYLXQU+dqFVCgjR6m+GE77zPvJLfeHzZLYTSfA5TQMYnFzXKXC1Wk9OIVDWfZtHYXGSXinZUaYy8hvFNTK4WuFhERPryvWK2Gyo7TNsDE24rCS533AiJeblUhUzL9GyBbWTwWHu Private key D: 92195335224036372050432491275911478024654861793739812431498491339843473154074 Decrypted private key D: 92195335224036372050432491275911478024654861793739812431498491339843473154074 Private key G: (6b17d1f2e12c4247f8bce6e563a440f277037d812deb33a0f4a13945d898c296,4fe342e2fe1a7f9b8ee7eb4a7c0f9e162bce33576b315ececbb6406837bf51f5,1,ffffffff00000001000000000000000000000000fffffffffffffffffffffffc) Decrypted private key G: (6b17d1f2e12c4247f8bce6e563a440f277037d812deb33a0f4a13945d898c296,4fe342e2fe1a7f9b8ee7eb4a7c0f9e162bce33576b315ececbb6406837bf51f5,1,ffffffff00000001000000000000000000000000fffffffffffffffffffffffc) Private key A: ffffffff00000001000000000000000000000000fffffffffffffffffffffffc Private key A: ffffffff00000001000000000000000000000000fffffffffffffffffffffffc Private key B: 5ac635d8aa3a93e7b3ebbd55769886bc651d06b0cc53b0f63bce3c3e27d2604b Private key B: 5ac635d8aa3a93e7b3ebbd55769886bc651d06b0cc53b0f63bce3c3e27d2604b Private key Order: 115792089210356248762697446949407573529996955224135760342422259061068512044369 Private key Order: 115792089210356248762697446949407573529996955224135760342422259061068512044369 Private key field size p: 256 Private keyfield size p: 256 Encrypted private key (hex): 308202A8302206092A864886F70D0105013015041000112233445566778899AABBCCDDEEFF0201010482028019A1BF984F7D25A2D5CBFC3890A076755EF13541FA39C249624214AFBEE671F3A7324C6609B5D5351223C942BB741F4357406867642784140FF833DF5B31DD15CA4801D4B574591C6F02721C88600ACA105C2CBCE0AF4B31B373FE810544C26B4DE88362865F58739D429E8B0EF49C992EA6BA4EDDF0B9282EA2346419BE02A3D3D1F3C3F4A54158BBDB8399BC2366D8F6997B728243ADF0BCAD6863D630482CB06A5CD019226F53145DEC6BE4351A7D3EC7A7BCEF2761596B8FE1BBE615F526DFBDF8B17874AB8E6747167045395D19713837FD6107352F9C63593A55215BB4D40518AA6A68D6475E647C14208EE7B2C9937D12C5625A4F62EA56E01FB12161964AD4BC39702FD0BE83EDCD8AC264EECEA999F571A6F8A240B55AC425D82319E5947D3AC20D2C8F4DA1E576F4A0AF91F2B618191928C290A9C7C17FC898528904B972D5420F0D0869C10751C672C439A7AF678CA9304BEDD6B984A3029358B802E5E02106C994CB5CFFD0DE8534CFB1603AD1099511FA202EB975B82324983756E0F7AA02B48BAF01769A8032D780D683FF01E41FB49FC68C30036D2E50554DEE56D73F74E066658B9F3F1CB2748B814A71EEAAE26539EEB9AB421121C997FC58D33475A54EA8FE921A66054522529F6AADBDD25EA6523BF8EB5F9B459D18119B0734BF4A2D7407DC2877ECC349D109546B7D078955EB091BA70D9ADDA6AF4B02D63F526C4FF89686EEADB66B9635AC4665EC66308934952C811D860B5D053E76A1550A08D1EA6F8613BEF33EF24B7DE1F364B61349F0394D03189C5CD72970B55A4F4E2150D67D9B476171925E29D951A632F21BC53532B85AE1611113EBCAF58AD86CA8ED336C0C4DB8AC24B9DF702225E6E55215332FD1B205B593C161EE
and where D is the private key, and G is the base point on the curve. We can also try secp256k1:
Curve: secp256k1 Password: Hello World! Salt: 00112233445566778899AABBCCDDEEFF00 Method: PBEwithMD2andDES-CBC Encrypted private key: MIICeDAiBgkqhkiG9w0BBQEwFQQQABEiM0RVZneImaq7zN3u/wIBAQSCAlCCFS607POw0Eln8g3dpc0JgNapT/41j7HXG69F1OF1kKpgfcLO+58b83oRktGfMTsNLjW89Y1TofKiRzI+jZxWGi0GiFh8P0mqyP/cIHi5l8AlKU0Gc4IjC21/Tp/AVWQAs3f1LuIpTwvC4QMP95Pq92lnZKj/8TZENZXQvpwlD65GoD9F6UOktnRVN+dGgAj5Ba1N6wX+A+UJZjeQiDdTe54fvbGrj9Ye4jifdD1m0M1qZdwWVDT3XPjlmPpERBYZnWTk7WF0Jc25zuWNrNx5+a8Anvr41HYlBuO5xKPBQQKvQq3LMk5LkNgWVstuy8cdLXrLhRgoCMrOonnvs+ztKJumfAhhESRg9cGpeVonC9L4UY3W4zmNZj1FnsQ4bELT8Qae/VlSq5o3gKLfZNgyY1LZQ0XkjJCmRrX+F5tDhNbnDmWsOUV/2EGSlxXRDSfsmKB54+bHSww+8QmLdponI2NvGFOHoG7WN8/OJ3GmcC3ixTRLzBumIJSIk+CgDnZFzxUqQT15cCYy5L3CCM55os9OE0xeU5DYj2mRAuValo/0Jy5YcZPrL4wk2bqBqQ76xrwyteOyS4mOVE+QjYOsn9pyrtzMxXqZ86FSNk+qdhCJ0nUDMW3kCW38rd/YLh9Z/2Oq/D1YitAiG3ZR7g7hVDQTpfQ7Q+h8cizPVCeRsBg4zfjJr+RuCYiO5Ok/bjnDmAQ9uUfb7xocFlqs+cauFMENF74Qru44sgRbofLYWnd7EuFmL3jmEmtIKBhHv/DjN8XTjTZLcm/SHYroGFSo Private key D: 8238300842941714251323638590978168453833826303449553972470952864076683284568 Decrypted private key D: 8238300842941714251323638590978168453833826303449553972470952864076683284568 Private key G: (79be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798,483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8,1,0) Decrypted private key G: (79be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798,483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8,1,0) Private key A: 0 Private key A: 0 Private key B: 7 Private key B: 7 Private key Order: 115792089237316195423570985008687907852837564279074904382605163141518161494337 Private key Order: 115792089237316195423570985008687907852837564279074904382605163141518161494337 Private key field size p: 256 Private keyfield size p: 256 Encrypted private key (hex): 30820278302206092A864886F70D0105013015041000112233445566778899AABBCCDDEEFF0201010482025082152EB4ECF3B0D04967F20DDDA5CD0980D6A94FFE358FB1D71BAF45D4E17590AA607DC2CEFB9F1BF37A1192D19F313B0D2E35BCF58D53A1F2A247323E8D9C561A2D0688587C3F49AAC8FFDC2078B997C025294D067382230B6D7F4E9FC0556400B377F52EE2294F0BC2E1030FF793EAF7696764A8FFF136443595D0BE9C250FAE46A03F45E943A4B6745537E7468008F905AD4DEB05FE03E5096637908837537B9E1FBDB1AB8FD61EE2389F743D66D0CD6A65DC165434F75CF8E598FA444416199D64E4ED617425CDB9CEE58DACDC79F9AF009EFAF8D4762506E3B9C4A3C14102AF42ADCB324E4B90D81656CB6ECBC71D2D7ACB85182808CACEA279EFB3ECED289BA67C0861112460F5C1A9795A270BD2F8518DD6E3398D663D459EC4386C42D3F1069EFD5952AB9A3780A2DF64D8326352D94345E48C90A646B5FE179B4384D6E70E65AC39457FD841929715D10D27EC98A079E3E6C74B0C3EF1098B769A2723636F185387A06ED637CFCE2771A6702DE2C5344BCC1BA620948893E0A00E7645CF152A413D79702632E4BDC208CE79A2CF4E134C5E5390D88F699102E55A968FF4272E587193EB2F8C24D9BA81A90EFAC6BC32B5E3B24B898E544F908D83AC9FDA72AEDCCCC57A99F3A152364FAA761089D27503316DE4096DFCADDFD82E1F59FF63AAFC3D588AD0221B7651EE0EE1543413A5F43B43E87C722CCF542791B01838CDF8C9AFE46E09888EE4E93F6E39C398043DB947DBEF1A1C165AACF9C6AE14C10D17BE10AEEE38B2045BA1F2D85A777B12E1662F78E6126B48281847BFF0E337C5D38D364B726FD21D8AE81854A8
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.