// Copyright (c) .NET Foundation. All rights reserved. // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. using System; using System.Globalization; using System.Text; using Moq; using Xunit; namespace Microsoft.AspNetCore.DataProtection { public class DataProtectionAdvancedExtensionsTests { private const string SampleEncodedString = "AQI"; // = WebEncoders.Base64UrlEncode({ 0x01, 0x02 }) [Fact] public void Protect_PayloadAsString_WithExplicitExpiration() { // Arrange var plaintextAsBytes = Encoding.UTF8.GetBytes("this is plaintext"); var expiration = StringToDateTime("2015-01-01 00:00:00Z"); var mockDataProtector = new Mock(); mockDataProtector.Setup(o => o.Protect(plaintextAsBytes, expiration)).Returns(new byte[] { 0x01, 0x02 }); // Act string protectedPayload = mockDataProtector.Object.Protect("this is plaintext", expiration); // Assert Assert.Equal(SampleEncodedString, protectedPayload); } [Fact] public void Protect_PayloadAsString_WithLifetimeAsTimeSpan() { // Arrange var plaintextAsBytes = Encoding.UTF8.GetBytes("this is plaintext"); DateTimeOffset actualExpiration = default(DateTimeOffset); var mockDataProtector = new Mock(); mockDataProtector.Setup(o => o.Protect(plaintextAsBytes, It.IsAny())) .Returns((_, exp) => { actualExpiration = exp; return new byte[] { 0x01, 0x02 }; }); // Act DateTimeOffset lowerBound = DateTimeOffset.UtcNow.AddHours(48); string protectedPayload = mockDataProtector.Object.Protect("this is plaintext", TimeSpan.FromHours(48)); DateTimeOffset upperBound = DateTimeOffset.UtcNow.AddHours(48); // Assert Assert.Equal(SampleEncodedString, protectedPayload); Assert.InRange(actualExpiration, lowerBound, upperBound); } [Fact] public void Protect_PayloadAsBytes_WithLifetimeAsTimeSpan() { // Arrange DateTimeOffset actualExpiration = default(DateTimeOffset); var mockDataProtector = new Mock(); mockDataProtector.Setup(o => o.Protect(new byte[] { 0x11, 0x22, 0x33 }, It.IsAny())) .Returns((_, exp) => { actualExpiration = exp; return new byte[] { 0x01, 0x02 }; }); // Act DateTimeOffset lowerBound = DateTimeOffset.UtcNow.AddHours(48); byte[] protectedPayload = mockDataProtector.Object.Protect(new byte[] { 0x11, 0x22, 0x33 }, TimeSpan.FromHours(48)); DateTimeOffset upperBound = DateTimeOffset.UtcNow.AddHours(48); // Assert Assert.Equal(new byte[] { 0x01, 0x02 }, protectedPayload); Assert.InRange(actualExpiration, lowerBound, upperBound); } [Fact] public void Unprotect_PayloadAsString() { // Arrange var futureDate = DateTimeOffset.UtcNow.AddYears(1); var controlExpiration = futureDate; var mockDataProtector = new Mock(); mockDataProtector.Setup(o => o.Unprotect(new byte[] { 0x01, 0x02 }, out controlExpiration)).Returns(Encoding.UTF8.GetBytes("this is plaintext")); // Act DateTimeOffset testExpiration; string unprotectedPayload = mockDataProtector.Object.Unprotect(SampleEncodedString, out testExpiration); // Assert Assert.Equal("this is plaintext", unprotectedPayload); Assert.Equal(futureDate, testExpiration); } private static DateTime StringToDateTime(string input) { return DateTimeOffset.ParseExact(input, "u", CultureInfo.InvariantCulture).UtcDateTime; } } }