コード例 #1
0
        public void CanVerifySignature()
        {
            var tests = new[]
            {
                new
                {
                    Address    = "15jZVzLc9cXz5PUFFda5A4Z7kZDYPg2NnL",
                    PrivateKey = "L3TiCqmvPkXJpzCCZJuhy6wQtJZWDkR1AuqFY4Utib5J5XLuvLdZ",
                    Message    = "This is an example of a signed message.",
                    Signature  = "H6sliOnVrD9r+J8boZAKHZwBIW2zLiD72IfTIF94bfZhBI0JdMu9AM9rrF7P6eH+866YvM4H9xWGVN4jMJZycFU="
                },
                new
                {
                    Address    = "1QFqqMUD55ZV3PJEJZtaKCsQmjLT6JkjvJ",
                    PrivateKey = "5HxWvvfubhXpYYpS3tJkw6fq9jE9j18THftkZjHHfmFiWtmAbrj",
                    Message    = "hello world",
                    Signature  = "G+dnSEywl3v1ijlWXvpY6zpu+AKNNXJcVmrdE35m0mMlzwFzXDiNg+uZrG9k8mpQL6sjHKrlBoDNSA+yaPW7PEA="
                },
                new
                {
                    Address    = "1Q1wVsNNiUo68caU7BfyFFQ8fVBqxC2DSc",
                    PrivateKey = null as string,
                    Message    = "Localbitcoins.com will change the world",
                    Signature  = "IJ/17TjGGUqmEppAliYBUesKHoHzfY4gR4DW0Yg7QzrHUB5FwX1uTJ/H21CF8ncY8HHNB5/lh8kPAOeD5QxV8Xc="
                },
                new
                {
                    Address    = "1GvPJp7H8UYsYDvE4GFoV4f2gSCNZzGF48",
                    PrivateKey = "5JEeah4w29axvf5Yg9v9PKv86zcCN9qVbizJDMHmiSUxBqDFoUT",
                    Message    = "This is an example of a signed message2",
                    Signature  = "G8YNwlo+I36Ct+hZKGSBFl3q8Kbx1pxPpwQmwdsG85io76+DUOHXqh/DfBq+Cn2R3C3dI//g3koSjxy7yNxJ9m8="
                },
                new
                {
                    Address    = "1GvPJp7H8UYsYDvE4GFoV4f2gSCNZzGF48",
                    PrivateKey = "5JEeah4w29axvf5Yg9v9PKv86zcCN9qVbizJDMHmiSUxBqDFoUT",
                    Message    = "this is a very long messagethis is a very long messagethis is a very long messagethis is a very long messagethis is a very long messagethis is a very long messagethis is a very long messagethis is a very long messagethis is a very long messagethis is a very long messagethis is a very long messagethis is a very long messagethis is a very long messagethis is a very long messagethis is a very long messagethis is a very long messagethis is a very long messagethis is a very long messagethis is a very long messagethis is a very long message",
                    Signature  = "HFKBHewleUsotk6fWG0OvWS/E2pP4o5hixdD6ui60in/x4376FBI4DvtJYrljXLNJTG1pBOZG+qRT/7S9WiIBfQ="
                },
            };


            foreach (var test in tests)
            {
                if (test.PrivateKey != null)
                {
                    var secret    = Network.Main.CreateBitcoinSecret(test.PrivateKey);
                    var signature = secret.PrivateKey.SignMessage(test.Message);
                    Assert.True(((BitcoinPubKeyAddress)Network.Main.CreateBitcoinAddress(test.Address)).VerifyMessage(test.Message, signature));
                    Assert.True(secret.PubKey.VerifyMessage(test.Message, signature));
                }
                BitcoinPubKeyAddress address = (BitcoinPubKeyAddress)Network.Main.CreateBitcoinAddress(test.Address);
                Assert.True(address.VerifyMessage(test.Message, test.Signature));
                Assert.True(!address.VerifyMessage("bad message", test.Signature));
            }
        }
コード例 #2
0
        public static void ProvingYouOwnAnAddress()
        {
            // the first ever Bitcoin transaction

            /*var bitcoinPrivateKey = new BitcoinSecret("XXXXXXXXXXXXXXXXXXXXXXXXXX");
             *
             * var message = "I am Craig Wright";
             * string signature = bitcoinPrivateKey.PrivateKey.SignMessage(message);
             * Console.WriteLine(signature); // IN5v9+3HGW1q71OqQ1boSZTm0/DCiMpI8E4JB1nD67TCbIVMRk/e3KrTT9GvOuu3NGN0w8R2lWOV2cxnBp+Of8c=*/

            // let's verify it
            var message   = "I am Craig Wright";
            var signature = "IN5v9+3HGW1q71OqQ1boSZTm0/DCiMpI8E4JB1nD67TCbIVMRk/e3KrTT9GvOuu3NGN0w8R2lWOV2cxnBp+Of8c=";

            var  address = new BitcoinPubKeyAddress("1A1zP1eP5QGefi2DMPTfTL5SLmv7DivfNa");
            bool isCraigWrightSatoshi = address.VerifyMessage(message, signature);

            Console.WriteLine("Is Craig Wright Satoshi? " + isCraigWrightSatoshi);
            // the bool is false, Craig was using social engineering
            // You prove you are the owner of an addess without moving coins by giving out the following:

            // Address: 1KF8kUVHK42XzgcmJF4Lxz4wcL5WDL97PB
            // Message: Nicolas Dorier Book Funding Address
            // Signature: H1jiXPzun3rXi0N9v9R5fAWrfEae9WPmlL5DJBj1eTStSvpKdRR8Io6/uT9tGH/3OnzG6ym5yytuWoA9ahkC3dQ=
        }
コード例 #3
0
        static string[] ReadMsgTxn(string MsgData)
        {
            byte[] bts         = MsgData.ToLower().HexToByteArray();
            string TxnHex      = WriteBts(bts, 0, 16).ToHex();
            string LinkedTxn   = WriteBts(bts, 16, 16).ToHex();
            string FromAddress = WriteBts(bts, 32, 20).ToHex();
            string Signature   = WriteBts(bts, 52, 65).ToHex();
            string Message     = WriteBts(bts, 117, bts.Length - 117).ToHex();

            if (!string.IsNullOrEmpty(LinkedTxn) && LinkedTxn.HexToByteArray().Length != 16)
            {
                return(null);
            }
            if (TxnHex.HexToByteArray().Length != 16)
            {
                return(null);
            }
            System.Security.Cryptography.MD5 sha1 = System.Security.Cryptography.MD5.Create();
            if (TxnHex != sha1.ComputeHash(System.Text.Encoding.UTF8.GetBytes(FromAddress + Signature + Message)).ToHex())
            {
                return(null);
            }
            Network net = Network.Main;
            BitcoinPubKeyAddress bitcoinPubKeyAddress = new BitcoinPubKeyAddress(new KeyId(FromAddress.HexToByteArray()), net);

            Message     = System.Text.Encoding.UTF8.GetString(Message.HexToByteArray());
            Signature   = Convert.ToBase64String(Signature.HexToByteArray());
            FromAddress = bitcoinPubKeyAddress.ToString();
            if (bitcoinPubKeyAddress.VerifyMessage(Message, Signature) == false)
            {
                return(null);
            }
            return(new string[] { TxnHex, FromAddress, Signature, Message, LinkedTxn });
        }
コード例 #4
0
        static void VerifyMessage(Network network, string message, string signature, string address)
        {
            var  btcAddress = new BitcoinPubKeyAddress(address);
            bool confirmed  = btcAddress.VerifyMessage(message, signature);

            Console.WriteLine("The message, " + message + ", sent by, " + address + ", belongs to them: " + confirmed);
        }
コード例 #5
0
        public ViewResult Redeem(RedeemModel model)
        {
            var address = new BitcoinPubKeyAddress(model.Address);

            model.Challenge = CreateChallenge(address);
            if (model.Signature == "yes")
            {
                ModelState.AddModelError("Signature", "As if I will believe you... Proove it !");
            }
            try
            {
                if (!address.VerifyMessage(model.Challenge, model.Signature))
                {
                    return(Liar(model, address));
                }
            }
            catch
            {
                return(Liar(model, address));
            }

            if (!GetMakers().Makers.Any(m => m.Address.Equals(address)))
            {
                model.Message = "You did not solved challenge 1 !";
                return(View(model));
            }

            model.Message = "Here it is";
            model.Link    = "https://aois.blob.core.windows.net/public/Blockchain Programming in CSharp(PART II).pdf";
            return(View(model));
        }
コード例 #6
0
        static void VerifyDorier()
        {
            var address   = new BitcoinPubKeyAddress("1KF8kUVHK42XzgcmJF4Lxz4wcL5WDL97PB");
            var message   = "Nicolas Dorier Book Funding Address";
            var signature = "H1jiXPzun3rXi0N9v9R5fAWrfEae9WPmlL5DJBj1eTStSvpKdRR8Io6/uT9tGH/3OnzG6ym5yytuWoA9ahkC3dQ=";

            Console.WriteLine(address.VerifyMessage(message, signature));
        }
コード例 #7
0
        static void VerifyDorier()
        {
            //Exercise: Verify that Nicolas sensei is not lying!
            var addressOfTheBook        = new BitcoinPubKeyAddress("1KF8kUVHK42XzgcmJF4Lxz4wcL5WDL97PB");
            var messageWrittenByNicolas = "Nicolas Dorier Book Funding Address";
            var signatureByNicolas      = "H1jiXPzun3rXi0N9v9R5fAWrfEae9WPmlL5DJBj1eTStSvpKdRR8Io6/uT9tGH/3OnzG6ym5yytuWoA9ahkC3dQ=";

            Console.WriteLine($"address.VerifyMessage(message, signature): {addressOfTheBook.VerifyMessage(messageWrittenByNicolas, signatureByNicolas)}");
        }
コード例 #8
0
        public static void Authentication()
        {
            var message   = "Nicolas Dorier Book Funding Address";
            var address   = new BitcoinPubKeyAddress("1KF8kUVHK42XzgcmJF4Lxz4wcL5WDL97PB");
            var signature = "H1jiXPzun3rXi0N9v9R5fAWrfEae9WPmlL5DJBj1eTStSvpKdRR8Io6/uT9tGH/3OnzG6ym5yytuWoA9ahkC3dQ=";

            bool NicolasOwnsPrivateKeyOfBookAddress = address.VerifyMessage(message, signature);

            Console.WriteLine(NicolasOwnsPrivateKeyOfBookAddress); // True
        }
コード例 #9
0
        static void VerifySatoshi()
        {
            var message   = "I am Craig Wright";
            var signature = "IN5v9+3HGW1q71OqQ1boSZTm0/DCiMpI8E4JB1nD67TCbIVMRk/e3KrTT9GvOuu3NGN0w8R2lWOV2cxnBp+Of8c=";

            var  address = new BitcoinPubKeyAddress("1A1zP1eP5QGefi2DMPTfTL5SLmv7DivfNa");
            bool isCraigWrightSatoshi = address.VerifyMessage(message, signature);

            Console.WriteLine("Is Craig Wright Satoshi? " + isCraigWrightSatoshi);
        }
コード例 #10
0
        static void VerifySatoshi()
        {
            var messageWrittenByCraig = "I am Craig Wright";
            var signatureByCraig      = "IN5v9+3HGW1q71OqQ1boSZTm0/DCiMpI8E4JB1nD67TCbIVMRk/e3KrTT9GvOuu3NGN0w8R2lWOV2cxnBp+Of8c=";

            var bitcoinAddressOfTheFirstEver = new BitcoinPubKeyAddress("1A1zP1eP5QGefi2DMPTfTL5SLmv7DivfNa");

            bool isCraigWrightSatoshi = bitcoinAddressOfTheFirstEver.VerifyMessage(messageWrittenByCraig, signatureByCraig);

            Console.WriteLine($"isCraigWrightSatoshi: {isCraigWrightSatoshi}");
        }
コード例 #11
0
        private void Code7()
        {
            var address = new BitcoinPubKeyAddress("1KF8kUVHK42XzgcmJF4Lxz4wcL5WDL97PB");
            var msg     = "Nicolas Dorier Book Funding Address";
            var sig     = "H1jiXPzun3rXi0N9v9R5fAWrfEae9WPmlL5DJBj1eTStSvpKdRR8Io6/uT9tGH/3OnzG6ym5yytuWoA9ahkC3dQ=";

            Console.WriteLine(address.VerifyMessage(msg, sig));

            msg = "Prove me you are 1LUtd66PcpPx64GERqufPygYEWBQR2PUN6";
            sig = paymentSecret.PrivateKey.SignMessage(msg);
            Console.WriteLine(paymentSecret.GetAddress().VerifyMessage(msg, sig));
        }
コード例 #12
0
        public bool VerifyMessage(string pubKeyAddress, string message, string signedMessage)
        {
            var address = new BitcoinPubKeyAddress(pubKeyAddress);

            try
            {
                return(address.VerifyMessage(message, signedMessage));
            }
            catch
            {
                return(false);
            }
        }
コード例 #13
0
        private static void Main(string[] args)
        {
            // signing a message


            var          bitcoinPrivateKey = new BitcoinSecret("KzgjNRhcJ3HRjxVdFhv14BrYUKrYBzdoxQyR2iJBHG9SNGGgbmtC");
            const string message           = "Craig Wright is a fraud";
            string       signature         = bitcoinPrivateKey.PrivateKey.SignMessage(message);

            Console.WriteLine(signature);

            var genesisBlockAddress  = new BitcoinPubKeyAddress("1A1zP1eP5QGefi2DMPTfTL5SLmv7DivfNa");
            var isCraigWrightSatoshi = genesisBlockAddress.VerifyMessage(message, signature);

            Console.WriteLine($"Is Craig Wright Satoshi? {isCraigWrightSatoshi}!");

            var          bookAddress      = new BitcoinPubKeyAddress("1KF8kUVHK42XzgcmJF4Lxz4wcL5WDL97PB");
            const string DoriersMessage   = "Nicolas Dorier Book Funding Address";
            const string DoriersSignature = "H1jiXPzun3rXi0N9v9R5fAWrfEae9WPmlL5DJBj1eTStSvpKdRR8Io6/uT9tGH/3OnzG6ym5yytuWoA9ahkC3dQ=";

            var isDorierTheBookAddressOwner = bookAddress.VerifyMessage(DoriersMessage, DoriersSignature);

            Console.WriteLine(isDorierTheBookAddressOwner);

            // get first genisis block
            Block genesisBlock = Network.Main.GetGenesis();

            // get first tx
            Transaction firstEverTransaction = genesisBlock.Transactions.FirstOrDefault();

            // get first output
            TxOut firstEverOutput = firstEverTransaction?.Outputs.FirstOrDefault();

            // get first script pub key
            Script firstEverScriptPubKey = firstEverOutput?.ScriptPubKey;

            // get first public key
            PubKey firstEverPubKey = firstEverScriptPubKey?.GetDestinationPublicKeys().FirstOrDefault();

            // get bitcoin address from public key with network identifier
            BitcoinPubKeyAddress firstEverBitcoinAddress = firstEverPubKey?.GetAddress(Network.Main);

            Console.WriteLine($"{genesisBlock}\n{firstEverTransaction}\n" +
                              $"{firstEverOutput}\n{firstEverScriptPubKey}\n" +
                              $"{firstEverPubKey}\n{firstEverBitcoinAddress}");

            Console.ReadLine();
        }
コード例 #14
0
    public bool verifySignature(string address, string message, string signature)
    {
        if (checkAddressValid(address))
        {
            BitcoinPubKeyAddress addrs = new BitcoinPubKeyAddress(address);

            if (addrs.VerifyMessage(message, signature))
            {
                return(true);
            }
            else
            {
                return(false);
            }
        }
        return(false);
    }
コード例 #15
0
    void verifyAddress(string url)
    {
        if (url != null)
        {
            url = url.Replace(urlscheme + "://", "");
            url = url.Replace("sendaddress?", "");
            url = url.Replace("address=", "");
            url = url.Replace("&msg=", "PARSE");
            url = url.Replace("&sig=", "PARSE");

            string[] param = url.Split(new[] { "PARSE" }, StringSplitOptions.None);

            string address   = "";
            string signature = "";

            if (param.Length > 0)
            {
                address = param [0];
            }

            if (param.Length > 2)
            {
                signature = param [2];
            }

            try
            {
                BitcoinPubKeyAddress addrs = new BitcoinPubKeyAddress(address);

                if (addrs.VerifyMessage(randomMessage, signature))
                {
                    Debug.Log("Address verified!");

                    StartCoroutine(getAddressBalance(address));
                }
                else
                {
                    Debug.Log("Address not verified!");
                }
            }
            catch (System.FormatException e)
            {
                Debug.Log("address not valid");
            }
        }
    }
コード例 #16
0
        private static void ProofOfOwnership()
        {
            var message   = "I am Craig Wright";
            var signature = "IN5v9+3HGW1q71OqQ1boSZTm0/DCiMpI8E4JB1nD67TCbIVMRk/e3KrTT9GvOuu3NGN0w8R2lWOV2cxnBp+Of8c=";

            var  address = new BitcoinPubKeyAddress("1A1zP1eP5QGefi2DMPTfTL5SLmv7DivfNa");
            bool isCraigWrightSatoshi = address.VerifyMessage(message, signature);

            Console.WriteLine("Is Craig Wright Satoshi? " + isCraigWrightSatoshi);

            message   = "Nicolas Dorier Book Funding Address";
            signature = "H1jiXPzun3rXi0N9v9R5fAWrfEae9WPmlL5DJBj1eTStSvpKdRR8Io6/uT9tGH/3OnzG6ym5yytuWoA9ahkC3dQ=";

            address = new BitcoinPubKeyAddress("1KF8kUVHK42XzgcmJF4Lxz4wcL5WDL97PB");
            var isNicDorier = address.VerifyMessage(message, signature);

            Console.WriteLine("Is Nic Dorier? " + isNicDorier);
        }
コード例 #17
0
        public static SignatureVerificationResult Verify(string legacyAddreess, string messageToSign, string signature)
        {
            BitcoinPubKeyAddress bitcoinPubKeyAddress = new BitcoinPubKeyAddress(legacyAddreess, Network.Main);

            try
            {
                bool verified = bitcoinPubKeyAddress.VerifyMessage(messageToSign, signature);
                if (verified)
                {
                    return(SignatureVerificationResult.SignatureIsValid);
                }
                return(SignatureVerificationResult.SignatureDoesntMatchMessage);
            }
            catch
            {
                return(SignatureVerificationResult.StringSentIsNotASignature);
            }
        }
コード例 #18
0
 private void Verify_Button_Click(object sender, RoutedEventArgs e)
 {
     try
     {
         var address = new BitcoinPubKeyAddress(Address.Text, Network.Main);
         if (address.VerifyMessage(message.Text, signature.Text))
         {
             MessageBox.Show("Signature Verified", "verify Message", MessageBoxButton.OK);
         }
         else
         {
             MessageBox.Show("Wrong Signature", "verify Message", MessageBoxButton.OK);
         }
     }
     catch (Exception ex)
     {
         MessageBox.Show(ex.Message, "Warning", MessageBoxButton.OK);
     }
 }
コード例 #19
0
        static void Test(string[] args)
        {
            var    bitcoinPrivateKey = new BitcoinSecret("L46GfzE4z24gmX7d3MTWh2dRjTpd6jv4SB3zTB88uvFniMwTbg4B");
            var    message           = "I am ugo the jedi master";
            string signature         = bitcoinPrivateKey.PrivateKey.SignMessage(message);

            Console.WriteLine(signature);

            var  address            = new BitcoinPubKeyAddress("16LyFzae8r9a1tny8n66gCdrLXUPPcaRm8");
            bool isUgoTheJediMaster = address.VerifyMessage(message, signature);

            Console.WriteLine(isUgoTheJediMaster);

            //verify nicholas doria is the owner of this address:
            var  nicholasSignature = "H1jiXPzun3rXi0N9v9R5fAWrfEae9WPmlL5DJBj1eTStSvpKdRR8Io6/uT9tGH/3OnzG6ym5yytuWoA9ahkC3dQ=";
            var  nicholasAddress   = new BitcoinPubKeyAddress("1KF8kUVHK42XzgcmJF4Lxz4wcL5WDL97PB");
            var  nicholasMessage   = "Nicolas Dorier Book Funding Address";
            bool isNicholasAddress = nicholasAddress.VerifyMessage(nicholasMessage, nicholasSignature);

            Console.ReadKey();
        }
コード例 #20
0
        public static void Execute()
        {
            var bitcoinSecret = new BitcoinSecret("cUyeaNoyfYQYC43sxozcyUvwhP6AHQK9ajBqtV23MbdEDxTuxgkT");

            string message   = "I am Craig Wright";
            string signature = bitcoinSecret.PrivateKey.SignMessage(message);

            Console.WriteLine(signature);
            // IN5v9+3HGW1q71OqQ1boSZTm0/DCiMpI8E4JB1nD67TCbIVMRk/e3KrTT9GvOuu3NGN0w8R2lWOV2cxnBp+Of8c=

            // first ever bitcoin address, associated with the
            // genesis block: 1A1zP1eP5QGefi2DMPTfTL5SLmv7DivfNa and verify 'Craig Wright' claim
            message   = "I am Craig Wright";
            signature = "IN5v9+3HGW1q71OqQ1boSZTm0/DCiMpI8E4JB1nD67TCbIVMRk/e3KrTT9GvOuu3NGN0w8R2lWOV2cxnBp+Of8c=";

            var  address = new BitcoinPubKeyAddress("1A1zP1eP5QGefi2DMPTfTL5SLmv7DivfNa");
            bool isCraigWrightSatoshi = address.VerifyMessage(message, signature);

            Console.WriteLine("Is Craig Wright Satoshi? " + isCraigWrightSatoshi);

            /*
             * prove you are the owner of an address without moving coins
             * Address:1KF8kUVHK42XzgcmJF4Lxz4wcL5WDL97PB
             * Message:Nicolas Dorier Book Funding Address
             * Signature:H1jiXPzun3rXi0N9v9R5fAWrfEae9WPmlL5DJBj1eTStSvpKdRR8Io6/uT9tGH/3OnzG6ym5yytuWoA9ahkC3dQ=
             */

            var address2   = "1KF8kUVHK42XzgcmJF4Lxz4wcL5WDL97PB";
            var message2   = "Nicolas Dorier Book Funding Address";
            var signature2 = "H1jiXPzun3rXi0N9v9R5fAWrfEae9WPmlL5DJBj1eTStSvpKdRR8Io6/uT9tGH/3OnzG6ym5yytuWoA9ahkC3dQ=";

            //Verify that Nicolas sensei is not lying!
            var  bcAddress       = new BitcoinPubKeyAddress(address2);
            bool isNicolasDorier = bcAddress.VerifyMessage(message2, signature2);


            Console.WriteLine("Is isNicolasDorier Signature? " + isNicolasDorier);
            Console.ReadLine();
        }
コード例 #21
0
        public BitIdResponse VerifyMessage()
        {
            BitIdResponse response = new BitIdResponse();

            response.Success = false;

            if (!string.IsNullOrEmpty(Address) && !string.IsNullOrEmpty(Uri) && !string.IsNullOrEmpty(Signature))
            {
                string nonce       = Uri.Split('=')[1].Replace("&u", "");
                string hexTicks    = nonce.Substring(32, 15);
                long   ticks       = Convert.ToInt64(hexTicks, 16);
                double spanSeconds = DateTime.UtcNow.Subtract(new DateTime(ticks)).TotalSeconds;
                if (spanSeconds > Constants.SpanTimeInSeconds)
                {
                    response.Message = "Request timeout!";
                    return(response);
                }

                BitcoinPubKeyAddress testAddress = new BitcoinPubKeyAddress(Address);
                response.Success = testAddress.VerifyMessage(Uri, Signature);
                if (response.Success)
                {
                    response.Address   = Address;
                    response.Signature = Signature;
                }
                else
                {
                    response.Message = "Invalid signature!";
                }
            }
            else
            {
                response.Message = "Missing parameters!";
            }

            return(response);
        }
コード例 #22
0
        protected string _cacheVersionMark; // CSS cache buster

        protected static void ProcessRespondBitId(BitIdCredentials credentials, HttpResponse response)
        {
            BitcoinPubKeyAddress testAddress = new BitcoinPubKeyAddress(credentials.address);

            if (testAddress.VerifyMessage(credentials.uri, credentials.signature))
            {
                // woooooo

                try
                {
                    // Test for registration

                    string intent = GuidCache.Get(credentials.uri + "-Intent") as string;

                    if (!string.IsNullOrEmpty(intent))
                    {
                        if (intent.StartsWith("Register"))
                        {
                            int    personId = Int32.Parse(intent.Substring("Register-".Length));
                            Person person   = Person.FromIdentity(personId);
                            person.BitIdAddress = credentials.address;
                            GuidCache.Set(credentials.uri + "-Intent", "Complete");
                        }
                    }

                    // Otherwise, test for logon

                    if (GuidCache.Get(credentials.uri + "-Logon") as string == "Unauth")
                    {
                        Person person = Person.FromBitIdAddress(credentials.address);

                        // TODO: If above throws, show friendly "unknown wallet" message

                        int lastOrgId = person.LastLogonOrganizationId;

                        if (lastOrgId == 0)
                        {
                            lastOrgId = Organization.SandboxIdentity;
                            person.LastLogonOrganizationId = lastOrgId;
                        }

                        GuidCache.Set(credentials.uri + "-LoggedOn",
                                      Authority.FromLogin(person, Organization.FromIdentity(person.LastLogonOrganizationId)).ToEncryptedXml());
                    }
                }
                catch (Exception e)
                {
                    Persistence.Key["BitIdLogin_Debug_Exception"] = e.ToString();
                }

                // TODO: Error codes

                response.StatusCode = 200;
                response.SetJson();
                response.Write("{\"address\":\"" + credentials.address + "\",\"signature\":\"" + credentials.signature +
                               "\"}");
                response.End();
            }
            else
            {
                response.StatusCode = 401; // Be a bit more friendly in your return codes
            }
        }