Esempio n. 1
0
        /// <summary>
        /// Encrypt SD data with exchange key.
        /// </summary>
        /// <param name="plaintextList"></param>
        /// <param name="cert">Exchange key</param>
        /// <returns></returns>
        public SecurityDomainRestoreData EncryptForRestore(PlaintextList plaintextList, X509Certificate2 cert)
        {
            try
            {
                SecurityDomainRestoreData securityDomainRestoreData = new SecurityDomainRestoreData();
                securityDomainRestoreData.EncData.kdf = "sp108_kdf";

                byte[] master_key = Utils.GetRandom(32);

                foreach (Plaintext p in plaintextList.list)
                {
                    Datum      datum   = new Datum();
                    HMACSHA512 hmac    = new HMACSHA512();
                    byte[]     enc_key = KDF.sp800_108(master_key, p.tag, "", hmac, 512);

                    datum.tag = p.tag;
                    JWE jwe = new JWE();
                    jwe.Encrypt(enc_key, p.plaintext, "A256CBC-HS512", p.tag);
                    datum.compact_jwe = jwe.EncodeCompact();
                    securityDomainRestoreData.EncData.data.Add(datum);
                }

                // Now go make the wrapped key
                JWE jwe_wrapped = new JWE();
                jwe_wrapped.Encrypt(cert, master_key);
                securityDomainRestoreData.WrappedKey.enc_key = jwe_wrapped.EncodeCompact();
                securityDomainRestoreData.WrappedKey.x5t_256 = Base64UrlEncoder.Encode(Utils.Sha256Thumbprint(cert));
                return(securityDomainRestoreData);
            }
            catch (Exception ex)
            {
                throw new Exception("Failed to encrypt security domain data for restoring.", ex);
            }
        }
Esempio n. 2
0
        // 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);
        }