public static byte[] SHA1XorSecret(DiffieHellman dh, byte[] keyEx, byte[] encMacKey) { byte[] dhShared = dh.DecryptKeyExchange(keyEx); byte[] sha1DhShared = sha1.ComputeHash(EnsurePositive(dhShared)); if (sha1DhShared.Length != encMacKey.Length) throw new ArgumentOutOfRangeException(String.Format("encMacKey's length is not 20 bytes: [{0}]", ToBase64String(encMacKey))); byte[] secret = new byte[encMacKey.Length]; for (uint i = 0; i < encMacKey.Length; i++) { secret[i] = (byte) (encMacKey[i] ^ sha1DhShared[i]); } return secret; }
///<summary>Enables the SA if it has been properly setup.</summary> public void Enable() { // If both parties setup simultaneous SAs we could end up calling this // twice, once as a client and the other as server, this way we only // go through the whole process once. lock(_sync) { if(_called_enable == 1) { return; } else if(_closed == 1) { throw new Exception("Cannot enable a closed SA!"); } else if(_ldhe == null) { throw new Exception("Local DHE not set."); } else if(RDHE.Value == null) { throw new Exception("Remote DHE not set."); } else if(!_hash_verified) { throw new Exception("Hash is not verified!"); } else if(TimedOut) { throw new Exception("Timed out on this one!"); } _called_enable = 1; // Deriving the DHE exchange and determing the order of keys // Specifically, we need up to 4 keys for the sender/receiver encryption/ // authentication codes. So to determine the order, we say whomever has // the smallest gets the first set of keys. byte[] rdhe = (byte[]) RDHE.Value; RDHE = null; byte[] key = _dh.DecryptKeyExchange(rdhe); _dh.Clear(); _dh = null; int i = 0; while(i < _ldhe.Length && _ldhe[i] == rdhe[i]) i++; bool same = i == _ldhe.Length; bool first = !same && (_ldhe[i] < rdhe[i]); _ldhe = null; // Gathering our security parameter objects SecurityPolicy sp = SecurityPolicy.GetPolicy(_spi); SymmetricAlgorithm in_sa = sp.CreateSymmetricAlgorithm(); HashAlgorithm in_ha = sp.CreateHashAlgorithm(); SymmetricAlgorithm out_sa = sp.CreateSymmetricAlgorithm(); HashAlgorithm out_ha = sp.CreateHashAlgorithm(); // Generating the total key length int key_length = key.Length + 2 + (in_sa.KeySize / 8 + in_sa.BlockSize / 8) * 2; KeyedHashAlgorithm in_kha = in_ha as KeyedHashAlgorithm; KeyedHashAlgorithm out_kha = out_ha as KeyedHashAlgorithm; if(in_kha != null) { key_length += (in_kha.HashSize / 8) * 2; } // Generating a key by repeatedly hashing the DHE value and the key so far SHA1CryptoServiceProvider sha1 = new SHA1CryptoServiceProvider(); int usable_key_offset = key.Length; while(key.Length < key_length) { byte[] hash = sha1.ComputeHash(key); byte[] tmp_key = new byte[hash.Length + key.Length]; key.CopyTo(tmp_key, 0); hash.CopyTo(tmp_key, key.Length); key = tmp_key; } // Like a sub-session ID (see DTLS) short epoch = (short) ((key[usable_key_offset] << 8) + key[usable_key_offset + 1]); usable_key_offset += 2; byte[] key0 = new byte[in_sa.KeySize / 8]; Array.Copy(key, usable_key_offset, key0, 0, key0.Length); usable_key_offset += key0.Length; byte[] key1 = new byte[in_sa.KeySize / 8]; Array.Copy(key, usable_key_offset, key1, 0, key1.Length); usable_key_offset += key1.Length; // Same may occur if we are forming a session with ourselves! if(same) { in_sa.Key = key0; out_sa.Key = key0; } else if(first) { in_sa.Key = key0; out_sa.Key = key1; } else { out_sa.Key = key0; in_sa.Key = key1; } if(in_kha != null) { byte[] hkey0 = new byte[in_kha.HashSize / 8]; Array.Copy(key, usable_key_offset, hkey0, 0, hkey0.Length); usable_key_offset += hkey0.Length; byte[] hkey1 = new byte[in_kha.HashSize / 8]; Array.Copy(key, usable_key_offset, hkey1, 0, hkey1.Length); usable_key_offset += hkey1.Length; if(same) { in_kha.Key = hkey0; out_kha.Key = hkey0; } else if(first) { in_kha.Key = hkey0; out_kha.Key = hkey1; } else { out_kha.Key = hkey0; in_kha.Key = hkey1; } } SecurityHandler sh = new SecurityHandler(in_sa, out_sa, in_ha, out_ha, epoch); sh.Update += UpdateSH; SecurityHandler to_close = _current_sh; if(to_close != null) { to_close.Close(); } _current_sh = sh; _last_epoch = _current_epoch; _current_epoch = epoch; } // All finished set the state (which will probably fire an event) State = SAState.Active; }
public new static DiffieHellman Create() { return(DiffieHellman.Create("Mono.Security.Cryptography.DiffieHellman")); }
/**************** Static Methods *****************/ public static byte[] CreateAssociationRequest(DiffieHellman dh, NameValueCollection args) { byte[] dhPublic = dh.CreateKeyExchange(); string cpub = CryptUtil.UnsignedToBase64(dhPublic); DHParameters dhps = dh.ExportParameters(true); args.Add("openid.mode", "associate"); args.Add("openid.assoc_type", "HMAC-SHA1"); args.Add("openid.session_type", "DH-SHA1"); args.Add("openid.dh_modulus", CryptUtil.UnsignedToBase64(dhps.P)); args.Add("openid.dh_gen", CryptUtil.UnsignedToBase64(dhps.G)); args.Add("openid.dh_consumer_public", cpub); return ASCIIEncoding.ASCII.GetBytes(UriUtil.CreateQueryString(args)); }
private Association FetchAssociation(DiffieHellman dh, Uri serverUri, byte[] body) { try { FetchResponse resp = this.fetcher.Post(serverUri, body); NameValueCollection results = KVUtil.KVToDict(resp.data); return ParseAssociation(results, dh, serverUri); } catch (FetchException e) { if (e.response == null) { // XXX: log network failure } else if (e.response.code == HttpStatusCode.BadRequest) { // XXX: log this /* server_error = results.get('error', '<no message from server>') fmt = 'Getting association: error returned from server %s: %s' oidutil.log(fmt % (server_url, server_error)) */ } else { // XXX: log this /*fmt = 'Getting association: bad status code from server %s: %s' oidutil.log(fmt % (server_url, http_code)) */ } return null; } }
private static byte[] CreateAssociateRequest(DiffieHellman dh) { NameValueCollection args = new NameValueCollection(); return CreateAssociationRequest(dh, args); }
protected Association ParseAssociation(NameValueCollection results, DiffieHellman dh, Uri serverUri) { try { if (GetParameter(results, "assoc_type") != "HMAC-SHA1") { // XXX: log this return null; } byte[] secret; string sessionType = results["session_type"]; if (sessionType == null) { string macKey = results["mac_key"]; if (macKey == null) { // XXX: Log this return null; } secret = Convert.FromBase64String(macKey); } else { if (sessionType != "DH-SHA1") { // XXX: log this return null; } byte[] spub = Convert.FromBase64String(GetParameter(results, "dh_server_public")); byte[] encMacKey = Convert.FromBase64String(GetParameter(results, "enc_mac_key")); secret = CryptUtil.SHA1XorSecret(dh, spub, encMacKey); } string assocHandle = GetParameter(results, "assoc_handle"); TimeSpan expiresIn = new TimeSpan(0, 0, Convert.ToInt32(GetParameter(results, "expires_in"))); Association assoc = new HMACSHA1Association(assocHandle, secret, expiresIn); this.store.StoreAssociation(serverUri, assoc); return assoc; } catch (MissingParameterException e) { // XXX: log this return null; } }