/// <summary>Parse a revocation message.</summary> public UserRevocationMessage(Certificate cacert, MemBlock data) { _data = data; int pos = 0; int length = 0; Username = AdrConverter.Deserialize(data, pos, out length) as string; pos += length; // Random number to reduce likelihood of malicious duplication of messages NumberSerializer.ReadInt(data, pos); pos += 4; // Verify that there is a date contained therein, perhaps we should verify the time new DateTime(NumberSerializer.ReadLong(data, pos)); pos += 8; Signature = new byte[data.Length - pos]; data.Slice(pos).CopyTo(Signature, 0); // hash the data SHA1CryptoServiceProvider sha1 = new SHA1CryptoServiceProvider(); Hash = sha1.ComputeHash(data, 0, data.Length - Signature.Length); if (!cacert.PublicKey.VerifyHash(Hash, CryptoConfig.MapNameToOID("SHA1"), Signature)) { throw new Exception("Invalid UserRevocationMessage signature"); } }
/// <summary>Parses web data and updates the revoked users hashtable if /// successful</summary> protected void UpdateRl(byte[] data) { // message is length (4) + date (8) + data (variable) + hash (~20) int length = data.Length; if (length < 12) { throw new Exception("No data? Didn't get enough data..."); } length = NumberSerializer.ReadInt(data, 0); DateTime date = new DateTime(NumberSerializer.ReadLong(data, 4)); // warn the user that this is an old revocation list, maybe there is an attack if (date < DateTime.UtcNow.AddHours(-24)) { ProtocolLog.WriteIf(IpopLog.GroupVPN, "Revocation list is over 24 hours old"); } // Weird, data length is longer than the data we got if (length > data.Length - 12) { throw new Exception("Missing data? Didn't get enough data..."); } // hash the data and verify the signature SHA1CryptoServiceProvider sha1 = new SHA1CryptoServiceProvider(); byte[] hash = sha1.ComputeHash(data, 4, length); byte[] signature = new byte[data.Length - 4 - length]; Array.Copy(data, 4 + length, signature, 0, signature.Length); if (!_ca_cert.PublicKey.VerifyHash(hash, CryptoConfig.MapNameToOID("SHA1"), signature)) { throw new Exception("Invalid signature!"); } // convert the data to an array list as it was sent to us MemBlock mem = MemBlock.Reference(data, 12, length - 8); ArrayList rl = AdrConverter.Deserialize(mem) as ArrayList; if (rl == null) { throw new Exception("Data wasn't a list..."); } // convert it into a hashtable for O(1) look ups Hashtable ht = new Hashtable(); foreach (string username in rl) { ht[username] = true; } Interlocked.Exchange(ref _revoked_users, ht); }