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); } }
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); } }
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); } }
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); } }
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); } }
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); }
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); } }
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); }