c# - Does ECDiffieHellmanCng in .NET have a key derivation function that implements NIST SP 800-56A, section 5.8.1 -
i have task @ hand requires deriving key material using key derivation function described in nist sp 800-56a, section 5.8.1. i'm not expert in cryptography please excuse me if question naive. here's i've done far:
- i have other party's public key , private key
now try generate shared secret using ecdh 1.3.132.1.12 using c# (.net 4) ecdiffiehellmancng class so:
// getcngkey method reads private key certificate in personal certificate store cngkey cngprivatekey = getcngkey(); ecdiffiehellmancng ecdiffiehellmancng = new ecdiffiehellmancng(cngprivatekey); ecdiffiehellmancng.hashalgorithm = cngalgorithm.ecdiffiehellmanp256; ecdiffiehellmancng.keyderivationfunction = ?? // set here
finally this:
ecdiffiehellmancng.derivekeymaterial(otherpartypublickey:); where/how set other parameters algorithm id, party u info, party v info?
edit open using other libraries bouncy castle (provided can called .net)
tl;dr; haven't found way derive symmetric key using kdf described in nist sp 800-56a, section 5.8.1 using built-in classes in .net 4.0 alone
the news (for me :-)) is possible in .net 4.0 using lovely bouncycastle library (nuget: install-package bouncycastle-ext -version "1.7.0"). here's how:
step 1: other party's public key
depending on scenario, may read certificate or come part of message containing encrypted data. once have base64 encoded public-key, read org.bouncycastle.crypto.parameters.ecpublickeyparameters object so:
var publickeybytes = convert.frombase64string(base64pubkeystr); ecpublickeyparameters otherpartypublickey = (ecpublickeyparameters)publickeyfactory.createkey(publickeybytes); step 2: read private-key
this most-commonly involve reading private key pfx/p12 certificate. windows account running code should have access pfx/p12 , additionally, if certificate imported certificate store, you'll need grant permissions via tasks -> manage private key menu in certmgr.msc
using (streamreader reader = new streamreader(path)) { var fs = reader.basestream; string password = "<password pfx>"; pkcs12store store = new pkcs12store(fs, password.tochararray()); foreach (string n in store.aliases) { if (store.iskeyentry(n)) { asymmetrickeyentry asymmetrickey = store.getkey(n); if (asymmetrickey.key.isprivate) { ecprivatekeyparameters privatekey = asymmetrickey.key ecprivatekeyparameters; } } } } step 3: compute shared secret
ibasicagreement akeyagree = agreementutilities.getbasicagreement("ecdh"); akeyagree.init(privatekey); biginteger sharedsecret = akeyagree.calculateagreement(otherpartypublickey); byte[] sharedsecretbytes = sharedsecret.tobytearray(); step 4: prepare information required compute symmetric key:
byte[] algorithmid = encoding.ascii.getbytes(("<prependstring/hex>" + "id-aes256-gcm")); byte[] partyuinfo = encoding.ascii.getbytes("<as-per-agreement>"); byte[] partyvinfo = <as-per-agreement>; memorystream stream = new memorystream(algorithmid.length + partyuinfo.length + partyvinfo.length); var sr = new binarywriter(stream); sr.write(algorithmid); sr.flush(); sr.write(partyuinfo); sr.flush(); sr.write(partyvinfo); sr.flush(); stream.position = 0; byte[] keycalculationinfo = stream.getbuffer(); step 5: derive symmetric key
// note: use digest/hash function per agreement other party idigest digest = new sha256digest(); byte[] symmetrickey = new byte[digest.getdigestsize()]; digest.update((byte)(1 >> 24)); digest.update((byte)(1 >> 16)); digest.update((byte)(1 >> 8)); digest.update((byte)1); digest.blockupdate(sharedsecret, 0, sharedsecret.length); digest.blockupdate(keycalculationinfo, 0, keycalculationinfo.length); digest.dofinal(symmetrickey, 0); now have symmetric key ready decryption. perform decryption using aes, bouncycastle iwrapper can used. obtain iwrapper using org.bouncycastle.security.wrapperutilities calling wrapperutilities.getwrapper("aes//") e.g. "aes/cbc/pkcs7". depend on agreement between 2 communicating parties.
initialize cipher (iwrapper) symmetric key , initialization vector (iv) , call unwrap method plain-text bytes. finally, convert string literal using character encoding used (e.g. utf8/ascii/unicode)
Comments
Post a Comment