//----------------------------------------------------------------------- // // Copyright (c) Outercurve Foundation. All rights reserved. // //----------------------------------------------------------------------- namespace DotNetOpenAuth.Test.OpenId.ChannelElements { using System; using System.Collections.Generic; using System.Linq; using DotNetOpenAuth.Messaging; using DotNetOpenAuth.Messaging.Bindings; using DotNetOpenAuth.OpenId; using DotNetOpenAuth.OpenId.ChannelElements; using DotNetOpenAuth.OpenId.Messages; using DotNetOpenAuth.OpenId.Provider; using DotNetOpenAuth.Test.Mocks; using Moq; using NUnit.Framework; [TestFixture] public class SigningBindingElementTests : OpenIdTestBase { /// /// Verifies that the signatures generated match Known Good signatures. /// [Test] public void SignaturesMatchKnownGood() { Protocol protocol = Protocol.V20; var settings = new ProviderSecuritySettings(); var cryptoStore = new MemoryCryptoKeyStore(); byte[] associationSecret = Convert.FromBase64String("rsSwv1zPWfjPRQU80hciu8FPDC+GONAMJQ/AvSo1a2M="); string handle = "mock"; cryptoStore.StoreKey(ProviderAssociationKeyStorage.SharedAssociationBucket, handle, new CryptoKey(associationSecret, DateTime.UtcNow.AddDays(1))); var store = new ProviderAssociationKeyStorage(cryptoStore); SigningBindingElement signer = new ProviderSigningBindingElement(store, settings); signer.Channel = new TestChannel(this.MessageDescriptions); IndirectSignedResponse message = new IndirectSignedResponse(protocol.Version, new Uri("http://rp")); ITamperResistantOpenIdMessage signedMessage = message; message.ProviderEndpoint = new Uri("http://provider"); signedMessage.UtcCreationDate = DateTime.Parse("1/1/2009"); signedMessage.AssociationHandle = handle; Assert.IsNotNull(signer.ProcessOutgoingMessage(message)); Assert.AreEqual("o9+uN7qTaUS9v0otbHTuNAtbkpBm14+es9QnNo6IHD4=", signedMessage.Signature); } /// /// Verifies that all parameters in ExtraData in signed responses are signed. /// [Test] public void SignedResponsesIncludeExtraDataInSignature() { Protocol protocol = Protocol.Default; SigningBindingElement sbe = new ProviderSigningBindingElement(new ProviderAssociationHandleEncoder(new MemoryCryptoKeyStore()), new ProviderSecuritySettings()); sbe.Channel = new TestChannel(this.MessageDescriptions); IndirectSignedResponse response = new IndirectSignedResponse(protocol.Version, RPUri); response.ReturnTo = RPUri; response.ProviderEndpoint = OPUri; response.ExtraData["someunsigned"] = "value"; response.ExtraData["openid.somesigned"] = "value"; Assert.IsNotNull(sbe.ProcessOutgoingMessage(response)); ITamperResistantOpenIdMessage signedResponse = (ITamperResistantOpenIdMessage)response; // Make sure that the extra parameters are signed. // Since the signing algorithm only allows for signing parameters that start with // 'openid.', other parameters should not be signed. Assert.IsNotNull(signedResponse.SignedParameterOrder); string[] signedParameters = signedResponse.SignedParameterOrder.Split(','); Assert.IsTrue(signedParameters.Contains("somesigned")); Assert.IsFalse(signedParameters.Contains("someunsigned")); } /// /// Regression test for bug #45 (https://github.com/AArnott/dotnetopenid/issues/45) /// [Test, ExpectedException(typeof(ProtocolException))] public void MissingSignedParameter() { var cryptoStore = new MemoryCryptoKeyStore(); byte[] associationSecret = Convert.FromBase64String("rsSwv1zPWfjPRQU80hciu8FPDC+GONAMJQ/AvSo1a2M="); string handle = "{634477555066085461}{TTYcIg==}{32}"; cryptoStore.StoreKey(ProviderAssociationKeyStorage.PrivateAssociationBucket, handle, new CryptoKey(associationSecret, DateTime.UtcNow.AddDays(1))); var signer = new ProviderSigningBindingElement(new ProviderAssociationKeyStorage(cryptoStore), new ProviderSecuritySettings()); var testChannel = new TestChannel(new OpenIdProviderMessageFactory()); signer.Channel = testChannel; var buggyRPMessage = new Dictionary() { { "openid.assoc_handle", "{634477555066085461}{TTYcIg==}{32}" }, { "openid.claimed_id", "https://openid.stackexchange.com/user/f5e91123-e5b4-43c5-871f-5f276c75d31a" }, { "openid.identity", "https://openid.stackexchange.com/user/f5e91123-e5b4-43c5-871f-5f276c75d31a" }, { "openid.mode", "check_authentication" }, { "openid.op_endpoint", "https://openid.stackexchange.com/openid/provider" }, { "openid.response_nonce", "2011-08-01T00:32:10Zvdyt3efw" }, { "openid.return_to", "http://openid-consumer.appspot.com/finish?session_id=1543025&janrain_nonce=2011-08-01T00%3A32%3A09ZIPGz7D" }, { "openid.sig", "b0Rll6Kt1KKBWWBEg/qBvW3sQYtmhOUmpI0/UREBVZ0=" }, { "openid.signed", "claimed_id,identity,assoc_handle,op_endpoint,return_to,response_nonce,ns.sreg,sreg.email,sreg.fullname" }, { "openid.sreg.email", "kevin.montrose@stackoverflow.com" }, { "openid.sreg.fullname", "Kevin K Montrose" }, }; var message = (CheckAuthenticationRequest)testChannel.Receive(buggyRPMessage, new MessageReceivingEndpoint(OPUri, HttpDeliveryMethods.PostRequest)); var originalResponse = new IndirectSignedResponse(message, signer.Channel); signer.ProcessIncomingMessage(originalResponse); } } }