Beispiel #1
0
    public async Task CanEmbedMessagesInTheSignatureItself()
    {
        var(_, privateKey) = Generator.Ed25519KeyPair();
        var randomBytes = Generator.SHA384Hash();

        await using var fx = await TestAccount.CreateAsync(_network, fx => fx.CreateParams.InitialBalance = 0);

        await AssertHg.CryptoBalanceAsync(fx, 0);

        var transferAmount = Generator.Integer(10, 100);
        var receipt        = await fx.Client.TransferAsync(_network.Payer, fx.Record.Address, transferAmount, ctx =>
        {
            ctx.Signatory = new Signatory(_network.PrivateKey, new Signatory(CustomSigner));
        });

        Assert.Equal(ResponseCode.Success, receipt.Status);
        await AssertHg.CryptoBalanceAsync(fx, transferAmount);

        Task CustomSigner(IInvoice invoice)
        {
            var message    = Encoding.ASCII.GetBytes("This is an Embedded Message");
            var signingKey = TestKeys.ImportPrivateEd25519KeyFromBytes(privateKey);

            invoice.AddSignature(KeyType.Ed25519, message, message);
            return(Task.CompletedTask);
        }
    }
Beispiel #2
0
    public async Task UnrelatedPublicKeysCanSignUnrelatedMessage()
    {
        var(_, privateKey) = Generator.Ed25519KeyPair();
        await using var fx = await TestAccount.CreateAsync(_network, fx => fx.CreateParams.InitialBalance = 0);

        await AssertHg.CryptoBalanceAsync(fx, 0);

        var transferAmount = Generator.Integer(10, 100);
        var receipt        = await fx.Client.TransferAsync(_network.Payer, fx.Record.Address, transferAmount, ctx =>
        {
            ctx.Signatory = new Signatory(_network.PrivateKey, new Signatory(CustomSigner));
        });

        Assert.Equal(ResponseCode.Success, receipt.Status);
        await AssertHg.CryptoBalanceAsync(fx, transferAmount);

        Task CustomSigner(IInvoice invoice)
        {
            var randomBytes = Generator.SHA384Hash();
            var signingKey  = TestKeys.ImportPrivateEd25519KeyFromBytes(privateKey);
            var prefix      = signingKey.PublicKey.Export(KeyBlobFormat.PkixPublicKey).TakeLast(32).Take(6).ToArray();
            var signature   = SignatureAlgorithm.Ed25519.Sign(signingKey, randomBytes.Span);

            invoice.AddSignature(KeyType.Ed25519, prefix, signature);
            return(Task.CompletedTask);
        }
    }
Beispiel #3
0
    public async Task DuplicateSignaturesAreReduced()
    {
        await using var client = _network.NewClient();
        var(_, privateKey)     = Generator.Ed25519KeyPair();
        var invoice = new Invoice(new Proto.TransactionBody
        {
            TransactionID = new Proto.TransactionID(client.CreateNewTxId()),
            Memo          = Generator.String(20, 30)
        }, 0);
        var signatory = new Signatory(CustomSigner);

        await(signatory as ISignatory).SignAsync(invoice);
        var signedTransaction = invoice.GenerateSignedTransactionFromSignatures();
        var signatureMap      = signedTransaction.SigMap;

        Assert.Single(signatureMap.SigPair);
        Assert.Empty(signatureMap.SigPair[0].PubKeyPrefix);

        Task CustomSigner(IInvoice invoice)
        {
            for (int i = 0; i < Generator.Integer(3, 5); i++)
            {
                var signingKey = TestKeys.ImportPrivateEd25519KeyFromBytes(privateKey);
                var prefix     = signingKey.PublicKey.Export(KeyBlobFormat.PkixPublicKey).ToArray();
                var signature  = SignatureAlgorithm.Ed25519.Sign(signingKey, invoice.TxBytes.Span);
                invoice.AddSignature(KeyType.Ed25519, prefix, signature);
            }
            return(Task.CompletedTask);
        }
    }
Beispiel #4
0
    public async Task PrefixTrimAccountsForShortPrefixes()
    {
        var sigCount = Generator.Integer(5, 10);
        var prefix   = Encoding.ASCII.GetBytes(Generator.Code(sigCount + 10));

        await using var client = _network.NewClient();
        var invoice = new Invoice(new Proto.TransactionBody
        {
            TransactionID = new Proto.TransactionID(client.CreateNewTxId()),
            Memo          = Generator.String(20, 30)
        }, sigCount - 3);

        await(new Signatory(CustomSigner) as ISignatory).SignAsync(invoice);
        var signedTransaction = invoice.GenerateSignedTransactionFromSignatures();
        var signatureMap      = signedTransaction.SigMap;

        Assert.Equal(sigCount, signatureMap.SigPair.Count);
        for (int i = 0; i < signatureMap.SigPair.Count; i++)
        {
            Assert.Equal(i + 1, signatureMap.SigPair[i].PubKeyPrefix.Length);
        }
        Task CustomSigner(IInvoice invoice)
        {
            var signingKey = TestKeys.ImportPrivateEd25519KeyFromBytes(Generator.Ed25519KeyPair().privateKey);
            var signature  = SignatureAlgorithm.Ed25519.Sign(signingKey, invoice.TxBytes.Span);

            for (int i = 0; i < sigCount; i++)
            {
                var thumbprint = prefix.Take(1 + i).ToArray();
                invoice.AddSignature(KeyType.Ed25519, thumbprint, signature);
            }
            return(Task.CompletedTask);
        }
    }
Beispiel #5
0
    public async Task SignatureMapNoWithOneSignatureAndTrimLimitInlucdesPrefix()
    {
        await using var client = _network.NewClient();
        var(_, privateKey)     = Generator.Ed25519KeyPair();
        var trimLimit = Generator.Integer(5, 10);
        var invoice   = new Invoice(new Proto.TransactionBody
        {
            TransactionID = new Proto.TransactionID(client.CreateNewTxId()),
            Memo          = Generator.String(20, 30)
        }, trimLimit);
        var signatory = new Signatory(CustomSigner);

        await(signatory as ISignatory).SignAsync(invoice);
        var signedTransaction = invoice.GenerateSignedTransactionFromSignatures();
        var signatureMap      = signedTransaction.SigMap;

        Assert.Single(signatureMap.SigPair);
        Assert.Equal(trimLimit, signatureMap.SigPair[0].PubKeyPrefix.Length);

        Task CustomSigner(IInvoice invoice)
        {
            var signingKey = TestKeys.ImportPrivateEd25519KeyFromBytes(privateKey);
            var prefix     = signingKey.PublicKey.Export(KeyBlobFormat.PkixPublicKey).ToArray();
            var signature  = SignatureAlgorithm.Ed25519.Sign(signingKey, invoice.TxBytes.Span);

            invoice.AddSignature(KeyType.Ed25519, prefix, signature);
            return(Task.CompletedTask);
        }
    }
Beispiel #6
0
    public async Task AllowsDuplicateSignature()
    {
        await using var client = _network.NewClient();
        var payerKey     = TestKeys.ImportPrivateEd25519KeyFromBytes(_network.PrivateKey);
        var publicPrefix = payerKey.PublicKey.Export(KeyBlobFormat.PkixPublicKey).TakeLast(32).Take(6).ToArray();

        // Define Signing Method producing a duplicate signature
        Task CustomSigner(IInvoice invoice)
        {
            var goodSignature1 = SignatureAlgorithm.Ed25519.Sign(payerKey, invoice.TxBytes.Span);
            var goodSignature2 = SignatureAlgorithm.Ed25519.Sign(payerKey, invoice.TxBytes.Span);

            invoice.AddSignature(KeyType.Ed25519, publicPrefix, goodSignature1);
            invoice.AddSignature(KeyType.Ed25519, publicPrefix, goodSignature2);
            return(Task.CompletedTask);
        }

        var record = await client.TransferWithRecordAsync(_network.Payer, _network.Gateway, 100, ctx =>
        {
            ctx.Signatory = new Signatory(CustomSigner);
        });

        Assert.Equal(ResponseCode.Success, record.Status);
    }
Beispiel #7
0
    public async Task PrefixTrimLimitIsRespected()
    {
        var prefix   = Encoding.ASCII.GetBytes(Generator.String(10, 20));
        var sigCount = Generator.Integer(5, 10);

        await using var client = _network.NewClient();
        var invoice = new Invoice(new Proto.TransactionBody
        {
            TransactionID = new Proto.TransactionID(client.CreateNewTxId()),
            Memo          = Generator.String(20, 30)
        }, prefix.Length + 10);

        await(new Signatory(CustomSigner) as ISignatory).SignAsync(invoice);
        var signedTransaction = invoice.GenerateSignedTransactionFromSignatures();
        var signatureMap      = signedTransaction.SigMap;

        Assert.Equal(sigCount, signatureMap.SigPair.Count);
        foreach (var sig in signatureMap.SigPair)
        {
            Assert.Equal(prefix.Length, sig.PubKeyPrefix.Length);
        }

        Task CustomSigner(IInvoice invoice)
        {
            var signingKey = TestKeys.ImportPrivateEd25519KeyFromBytes(Generator.Ed25519KeyPair().privateKey);
            var signature  = SignatureAlgorithm.Ed25519.Sign(signingKey, invoice.TxBytes.Span);

            for (int i = 0; i < sigCount; i++)
            {
                var thumbprint = prefix.Clone() as byte[];
                thumbprint[thumbprint.Length - 1] = (byte)i;
                invoice.AddSignature(KeyType.Ed25519, thumbprint, signature);
            }
            return(Task.CompletedTask);
        }
    }
Beispiel #8
0
    public async Task InconsistentDuplicateSignatureRaisesError()
    {
        await using var client = _network.NewClient();
        var fakeKey1 = Key.Create(SignatureAlgorithm.Ed25519, new KeyCreationParameters {
            ExportPolicy = KeyExportPolicies.AllowPlaintextExport
        });
        var fakeKey2 = Key.Create(SignatureAlgorithm.Ed25519, new KeyCreationParameters {
            ExportPolicy = KeyExportPolicies.AllowPlaintextExport
        });
        var goodKey      = TestKeys.ImportPrivateEd25519KeyFromBytes(_network.PrivateKey);
        var publicPrefix = goodKey.PublicKey.Export(KeyBlobFormat.PkixPublicKey).TakeLast(32).Take(6).ToArray();

        // Define Defective Signing Method Bad Signature Last
        Task CustomSigner(IInvoice invoice)
        {
            var goodSignature = SignatureAlgorithm.Ed25519.Sign(goodKey, invoice.TxBytes.Span);
            var badSignature  = SignatureAlgorithm.Ed25519.Sign(fakeKey1, invoice.TxBytes.Span);

            invoice.AddSignature(KeyType.Ed25519, publicPrefix, goodSignature);
            invoice.AddSignature(KeyType.Ed25519, publicPrefix, badSignature);
            return(Task.CompletedTask);
        }

        var aex1 = await Assert.ThrowsAsync <ArgumentException>(async() =>
        {
            await client.TransferWithRecordAsync(_network.Payer, _network.Gateway, 100, ctx =>
            {
                ctx.Signatory = new Signatory(CustomSigner);
            });
        });

        Assert.StartsWith("Signature with Duplicate Prefix Identifier was provided, but did not have an Identical Signature.", aex1.Message);

        // Define Defective Signing Method Bad Signature First
        Task CustomSignerReverse(IInvoice invoice)
        {
            var goodSignature = SignatureAlgorithm.Ed25519.Sign(goodKey, invoice.TxBytes.Span);
            var badSignature  = SignatureAlgorithm.Ed25519.Sign(fakeKey1, invoice.TxBytes.Span);

            invoice.AddSignature(KeyType.Ed25519, publicPrefix, badSignature);
            invoice.AddSignature(KeyType.Ed25519, publicPrefix, goodSignature);
            return(Task.CompletedTask);
        }

        var aex2 = await Assert.ThrowsAsync <ArgumentException>(async() =>
        {
            await client.TransferWithRecordAsync(_network.Payer, _network.Gateway, 100, ctx =>
            {
                ctx.Signatory = new Signatory(CustomSignerReverse);
            });
        });

        Assert.StartsWith("Signature with Duplicate Prefix Identifier was provided, but did not have an Identical Signature.", aex2.Message);

        // Define Defective Signing Method Bad Two Bad Signatures
        Task CustomSignerBothBad(IInvoice invoice)
        {
            var badSignature1 = SignatureAlgorithm.Ed25519.Sign(fakeKey1, invoice.TxBytes.Span);
            var badSignature2 = SignatureAlgorithm.Ed25519.Sign(fakeKey2, invoice.TxBytes.Span);

            invoice.AddSignature(KeyType.Ed25519, publicPrefix, badSignature2);
            invoice.AddSignature(KeyType.Ed25519, publicPrefix, badSignature1);
            return(Task.CompletedTask);
        }

        // Inconsistent Key state should be checked before signatures are validated,
        // expecting an Argument exception and not a PreCheck exception.
        var aex3 = await Assert.ThrowsAsync <ArgumentException>(async() =>
        {
            await client.TransferWithRecordAsync(_network.Payer, _network.Gateway, 100, ctx =>
            {
                ctx.Signatory = new Signatory(CustomSignerBothBad);
            });
        });

        Assert.StartsWith("Signature with Duplicate Prefix Identifier was provided, but did not have an Identical Signature.", aex3.Message);
    }