-
Notifications
You must be signed in to change notification settings - Fork 14
Expand file tree
/
Copy pathEcdsaSigningExamples.cs
More file actions
126 lines (99 loc) · 5.11 KB
/
EcdsaSigningExamples.cs
File metadata and controls
126 lines (99 loc) · 5.11 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
using System.Security.Cryptography;
using System.Text;
using Secp256k1Net;
namespace Secp256k1Net.Examples;
/// <summary>
/// Examples demonstrating ECDSA signing and verification.
/// </summary>
public static class EcdsaSigningExamples
{
public static void Run()
{
Console.WriteLine("=== ECDSA Signing & Verification Examples ===\n");
SignAndVerifyExample();
SignRecoverableExample();
RecoverPublicKeyExample();
VerificationFailureExample();
}
/// <summary>
/// Sign(messageHash, secretKey) - Create a 64-byte compact ECDSA signature
/// Verify(signature, messageHash, publicKey) - Verify an ECDSA signature
/// </summary>
static void SignAndVerifyExample()
{
Console.WriteLine("--- Sign and Verify ---");
// Generate a key pair
var (secretKey, publicKey) = Secp256k1.CreateKeyPair(compressed: true);
// Create a message and hash it (ECDSA signs the hash, not the raw message)
string message = "Hello, secp256k1!";
byte[] messageHash = SHA256.HashData(Encoding.UTF8.GetBytes(message));
Console.WriteLine($"Message: {message}");
Console.WriteLine($"Message hash: {Convert.ToHexString(messageHash)}");
// Sign the message hash
byte[] signature = Secp256k1.Sign(messageHash, secretKey);
Console.WriteLine($"Signature ({signature.Length} bytes): {Convert.ToHexString(signature)}");
// Verify the signature
bool isValid = Secp256k1.Verify(signature, messageHash, publicKey);
Console.WriteLine($"Signature valid: {isValid}");
Console.WriteLine();
}
/// <summary>
/// SignRecoverable(messageHash, secretKey) - Create a recoverable signature with recovery ID
/// </summary>
static void SignRecoverableExample()
{
Console.WriteLine("--- SignRecoverable ---");
var (secretKey, publicKey) = Secp256k1.CreateKeyPair(compressed: true);
byte[] messageHash = SHA256.HashData("Recoverable signature example"u8);
// Create a recoverable signature (includes recovery ID)
(byte[] signature, byte recoveryId) = Secp256k1.SignRecoverable(messageHash, secretKey);
Console.WriteLine($"Signature: {Convert.ToHexString(signature)}");
Console.WriteLine($"Recovery ID: {recoveryId} (range 0-3)");
// The recovery ID allows reconstructing the public key from the signature
// This is used in Ethereum for transaction signatures (v, r, s format)
Console.WriteLine();
}
/// <summary>
/// RecoverPublicKey(signature, recoveryId, messageHash, compressed) - Recover public key from signature
/// </summary>
static void RecoverPublicKeyExample()
{
Console.WriteLine("--- RecoverPublicKey ---");
var (secretKey, originalPublicKey) = Secp256k1.CreateKeyPair(compressed: true);
byte[] messageHash = SHA256.HashData("Recovery test message"u8);
// Create a recoverable signature
(byte[] signature, byte recoveryId) = Secp256k1.SignRecoverable(messageHash, secretKey);
// Recover the public key using only the signature, recovery ID, and message hash
byte[] recoveredPublicKey = Secp256k1.RecoverPublicKey(signature, recoveryId, messageHash, compressed: true);
Console.WriteLine($"Original public key: {Convert.ToHexString(originalPublicKey)}");
Console.WriteLine($"Recovered public key: {Convert.ToHexString(recoveredPublicKey)}");
Console.WriteLine($"Keys match: {Convert.ToHexString(originalPublicKey).Equals(Convert.ToHexString(recoveredPublicKey))}");
// Can also recover to uncompressed format
byte[] recoveredUncompressed = Secp256k1.RecoverPublicKey(signature, recoveryId, messageHash, compressed: false);
Console.WriteLine($"Recovered uncompressed ({recoveredUncompressed.Length} bytes): {Convert.ToHexString(recoveredUncompressed)}");
Console.WriteLine();
}
/// <summary>
/// Demonstrates verification failures.
/// </summary>
static void VerificationFailureExample()
{
Console.WriteLine("--- Verification Failure Cases ---");
var (secretKey, publicKey) = Secp256k1.CreateKeyPair(compressed: true);
byte[] messageHash = SHA256.HashData("Original message"u8);
byte[] signature = Secp256k1.Sign(messageHash, secretKey);
// Verify with correct data
Console.WriteLine($"Correct verification: {Secp256k1.Verify(signature, messageHash, publicKey)}");
// Wrong message hash
byte[] wrongHash = SHA256.HashData("Different message"u8);
Console.WriteLine($"Wrong message hash: {Secp256k1.Verify(signature, wrongHash, publicKey)}");
// Wrong public key
var (_, wrongPublicKey) = Secp256k1.CreateKeyPair(compressed: true);
Console.WriteLine($"Wrong public key: {Secp256k1.Verify(signature, messageHash, wrongPublicKey)}");
// Corrupted signature
byte[] corruptedSig = (byte[])signature.Clone();
corruptedSig[0] ^= 0xFF;
Console.WriteLine($"Corrupted signature: {Secp256k1.Verify(corruptedSig, messageHash, publicKey)}");
Console.WriteLine();
}
}