private unsafe void CreateResumeTicket(Guid userToken, out byte[] ticket, out byte[] sessionSecret) { #if SQLCLR ticket = null; sessionSecret = null; #else State state = m_state; //Ticket Structure: // byte TicketVersion = 1 // Guid ServerKeyName // DateTime AuthenticationTime // byte[16] IV // byte[] Encrypted Session Data 32+16 // byte[32] HMAC (Sha2-256) const int encryptedLength = 32 + 16; const int ticketSize = 1 + 16 + 8 + 16 + encryptedLength + 32; byte[] initializationVector = SaltGenerator.Create(16); sessionSecret = SaltGenerator.Create(32); byte[] userTokenBytes = userToken.ToRfcBytes(); byte[] dataToEncrypt = new byte[encryptedLength]; sessionSecret.CopyTo(dataToEncrypt, 0); userTokenBytes.CopyTo(dataToEncrypt, sessionSecret.Length); ticket = new byte[ticketSize]; using (Aes aes = Cipher.CreateAes()) { aes.Key = state.ServerEncryptionkey; aes.IV = initializationVector; aes.Mode = CipherMode.CBC; aes.Padding = PaddingMode.None; ICryptoTransform decrypt = aes.CreateEncryptor(); byte[] encryptedData = decrypt.TransformFinalBlock(dataToEncrypt, 0, dataToEncrypt.Length); fixed(byte *lp = ticket) { BinaryStreamPointerWrapper stream = new BinaryStreamPointerWrapper(lp, ticket.Length); stream.Write((byte)1); stream.Write(state.ServerKeyName); stream.Write(DateTime.UtcNow.RoundDownToNearestMinute()); stream.Write(initializationVector); stream.Write(encryptedData); //Encrypted data, 32 byte session key, n byte user token stream.Write(HMAC <Sha256Digest> .Compute(state.ServerHMACKey, ticket, 0, ticket.Length - 32)); } } #endif }
public void TestHMACs2(int key, int value) { byte[] keyB = new byte[key]; byte[] valueB = new byte[value]; rng.GetBytes(keyB); rng.GetBytes(valueB); var code = HMAC <Sha1Digest> .Compute(keyB, valueB); HMACSHA1 hmac1 = new HMACSHA1(keyB); var code2 = hmac1.ComputeHash(valueB); if (!code.SequenceEqual(code2)) { throw new Exception(); } hmac1.Dispose(); }
private unsafe bool TryLoadTicket(byte[] ticket, out byte[] sessionSecret, out Guid userToken) { #if SQLCLR sessionSecret = null; userToken = Guid.Empty; return(false); #else State state = m_state; const int encryptedLength = 32 + 16; const int ticketSize = 1 + 16 + 8 + 16 + encryptedLength + 32; userToken = default(Guid); sessionSecret = null; //Ticket Structure: // byte TicketVersion = 1 // Guid ServerKeyName // DateTime AuthenticationTime // byte[16] IV // byte[] Encrypted Session Data 32+16 // byte[32] HMAC (Sha2-256) if (ticket == null || ticket.Length != ticketSize) return(false); fixed(byte *lp = ticket) { var stream = new BinaryStreamPointerWrapper(lp, ticket.Length); if (stream.ReadUInt8() != 1) { return(false); } if (!state.ServerKeyName.SecureEquals(stream.ReadGuid())) { return(false); } long currentTime = DateTime.UtcNow.Ticks; long issueTime = stream.ReadInt64(); if (issueTime <= currentTime) { //Issue time is before current time. if (currentTime - issueTime > TimeSpan.TicksPerMinute * TicketExpireTimeMinutes) { return(false); } } else { //For some reason, the issue time is after the current time. //This could be due to a clock sync on the server after the ticket was issued. //Allow up to 1 minute of clock skew if (issueTime - currentTime > TimeSpan.TicksPerMinute) { return(false); } } byte[] initializationVector = stream.ReadBytes(16); //Verify the signature if everything else looks good. //This is last because it is the most computationally complex. //This limits denial of service attackes. byte[] hmac = HMAC <Sha256Digest> .Compute(state.ServerHMACKey, ticket, 0, ticket.Length - 32); if (!hmac.SecureEquals(ticket, ticket.Length - 32, 32)) { return(false); } byte[] encryptedData = stream.ReadBytes(encryptedLength); var aes = new RijndaelManaged(); aes.Key = state.ServerEncryptionkey; aes.IV = initializationVector; aes.Mode = CipherMode.CBC; aes.Padding = PaddingMode.None; var decrypt = aes.CreateDecryptor(); encryptedData = decrypt.TransformFinalBlock(encryptedData, 0, encryptedData.Length); sessionSecret = new byte[32]; Array.Copy(encryptedData, 0, sessionSecret, 0, 32); userToken = encryptedData.ToRfcGuid(32); return(true); } #endif }