public void LoadKey(KeyPath path) { CertKey certKey = new CertKey(); certKey.Load(path); string encodedThumbprint = Base64UrlHelper.Encode(certKey.GetThumbprint()); _keys.Add(encodedThumbprint, certKey); }
private byte[] DecryptMasterKey(KeyPair decode_key_pair, CertKey certKey1, CertKey certKey2) { JWE jwe1 = new JWE(decode_key_pair.key1.enc_key); byte[] xor_key = jwe1.Decrypt(certKey1.GetKey()); JWE jwe2 = new JWE(decode_key_pair.key2.enc_key); byte[] derived_key = jwe2.Decrypt(certKey2.GetKey()); // Now, XOR to get the master key back byte[] master_key = new byte[xor_key.Length]; for (Int32 i = 0; i < xor_key.Length; ++i) { master_key[i] = (byte)(xor_key[i] ^ derived_key[i]); } return(master_key); }
// Internal worker function private PlaintextList Decrypt(SecurityDomainData data, CertKeys certKeys) { if (data.version == 2 && certKeys.Count() < data.SharedKeys.required) { throw new ArgumentException(string.Format(Resources.DecryptSecurityDomainKeyNotEnough, data.SharedKeys.required, certKeys.Count())); } byte[] masterKey; if (data.version == 1) { // ensure that the key splitting algorithm // is known, currently only one we know about if (data.SplitKeys.key_algorithm != "xor_split") { throw new Exception($"Unknown SplitKey algorithm {data.SplitKeys.key_algorithm}."); } KeyPair decodeKeyPair = null; CertKey certKey1 = null; CertKey certKey2 = null; foreach (KeyPair keyPair in data.SplitKeys.keys) { certKey1 = certKeys.Find(keyPair.key1.x5t_256); if (certKey1 == null) { continue; } certKey2 = certKeys.Find(keyPair.key2.x5t_256); if (certKey2 != null) { decodeKeyPair = keyPair; break; } } if (decodeKeyPair == null) { throw new Exception("Cannot find matching certs and keys for security domain"); } masterKey = DecryptMasterKey(decodeKeyPair, certKey1, certKey2); } else if (data.version == 2) { if (data.SharedKeys.key_algorithm != "shamir_share") { throw new Exception($"Unknown SharedKeys algorithm {data.SharedKeys.key_algorithm}"); } UInt32 shares_found = 0; List <UInt16[]> share_arrays = new List <UInt16[]>(); foreach (Key key in data.SharedKeys.enc_shares) { CertKey cert_key = certKeys.Find(key.x5t_256); if (cert_key != null) { JWE jwe = new JWE(key.enc_key); byte[] share = jwe.Decrypt(cert_key.GetKey()); shares_found++; share_arrays.Add(Utils.ConvertToUint16(share)); } if (share_arrays.Count == data.SharedKeys.required) { break; } } if (share_arrays.Count < data.SharedKeys.required) { throw new Exception($"Insufficient shares available. {data.SharedKeys.required} required, got {share_arrays.Count}."); } shared_secret secret = new shared_secret((UInt16)data.SharedKeys.required); masterKey = secret.get_secret(share_arrays); } else { throw new Exception($"Unknown domain version {data.version}."); } PlaintextList plaintextList = new PlaintextList(); // Need to check KDF foreach (Datum enc_data in data.EncData.data) { Plaintext p = new Plaintext(); HMACSHA512 hmac = new HMACSHA512(); byte[] enc_key = KDF.sp800_108(masterKey, enc_data.tag, "", hmac, 512); JWE jwe_data = new JWE(enc_data.compact_jwe); p.plaintext = jwe_data.Decrypt(enc_key); p.tag = enc_data.tag; plaintextList.Add(p); } return(plaintextList); }