public byte[] Protect(byte[] plaintext, DateTimeOffset expiration) { if (plaintext == null) { throw new ArgumentNullException(nameof(plaintext)); } // We prepend the expiration time (as a 64-bit UTC tick count) to the unprotected data. byte[] plaintextWithHeader = new byte[checked (8 + plaintext.Length)]; BitHelpers.WriteUInt64(plaintextWithHeader, 0, (ulong)expiration.UtcTicks); Buffer.BlockCopy(plaintext, 0, plaintextWithHeader, 8, plaintext.Length); return(GetInnerProtectorWithTimeLimitedPurpose().Protect(plaintextWithHeader)); }
internal byte[] UnprotectCore(byte[] protectedData, DateTimeOffset now, out DateTimeOffset expiration) { if (protectedData == null) { throw new ArgumentNullException(nameof(protectedData)); } try { byte[] plaintextWithHeader = GetInnerProtectorWithTimeLimitedPurpose().Unprotect(protectedData); if (plaintextWithHeader.Length < 8) { // header isn't present throw new CryptographicException(Resources.TimeLimitedDataProtector_PayloadInvalid); } // Read expiration time back out of the payload ulong utcTicksExpiration = BitHelpers.ReadUInt64(plaintextWithHeader, 0); DateTimeOffset embeddedExpiration = new DateTimeOffset(checked ((long)utcTicksExpiration), TimeSpan.Zero /* UTC */); // Are we expired? if (now > embeddedExpiration) { throw new CryptographicException(Resources.FormatTimeLimitedDataProtector_PayloadExpired(embeddedExpiration)); } // Not expired - split and return payload byte[] retVal = new byte[plaintextWithHeader.Length - 8]; Buffer.BlockCopy(plaintextWithHeader, 8, retVal, 0, retVal.Length); expiration = new DateTimeOffset((long)utcTicksExpiration, TimeSpan.Zero); return(retVal); } catch (Exception ex) when(ex.RequiresHomogenization()) { // Homogenize all failures to CryptographicException throw new CryptographicException(Resources.CryptCommon_GenericError, ex); } }