static void test_large_secret() { for (UInt32 i = 0; i < 1000000; ++i) { shared_secret ss = new shared_secret(11, 5); byte[] secret = new byte[32]; using (RNGCryptoServiceProvider rng = new RNGCryptoServiceProvider()) { rng.GetBytes(secret); } List <UInt16[]> share_arrays = ss.make_shares(secret); byte[] plaintext = ss.get_secret(share_arrays); if (!check_result(plaintext, secret)) { throw new Exception("test_large_secret failed"); } if ((i + 1) % 100000 == 0) { Console.WriteLine("{0} iterations", i + 1); } } Console.WriteLine("test_large_secret - success"); }
static void single_byte_test(byte shares, UInt16 required) { for (UInt16 i = 0; i < (UInt16)0x100; ++i) { shared_secret secret = new shared_secret(shares, required); UInt16[] share_array = secret.make_shares((byte)i); UInt16 result = secret.get_secret(share_array); if (i != result) { throw new Exception("single_byte_test failed"); } } }
static void random_single_byte_test() { byte shares = 126; UInt16 required = 16; for (UInt32 i = 0; i < 100000; ++i) { // just use i % 256 as the secret byte secret_value = (byte)(i % 256); shared_secret secret = new shared_secret(shares, required); UInt16[] share_array = secret.make_shares(secret_value); // Put them into a List so that we can pick them out List <UInt16> tmp_array = new List <UInt16>(); foreach (UInt16 u in share_array) { tmp_array.Add(u); } // Now need to randomly pick values UInt16[] random_shares = new UInt16[required]; random_bits bits = new random_bits(required); for (UInt32 j = 0; j < required; ++j) { // Yes, I really only need a byte, but this is test code UInt16 r = bits.get_word(); Int32 pos = (Int32)(r % tmp_array.Count); random_shares[j] = tmp_array[pos]; tmp_array.RemoveAt(pos); } UInt16 result = secret.get_secret(random_shares); if (result != secret_value) { throw new Exception("random_single_byte_test failed"); } } Console.WriteLine("random_single_byte_test - success"); }
// 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); }