-
Notifications
You must be signed in to change notification settings - Fork 846
/
BitcoinPubKeyAddress.cs
111 lines (96 loc) · 3.11 KB
/
BitcoinPubKeyAddress.cs
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
using NBitcoin.DataEncoders;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace NBitcoin
{
/// <summary>
/// Abstracts an object able to verify messages from which it is possible to extract public key.
/// </summary>
public interface IPubkeyHashUsable
{
bool VerifyMessage(string message, string signature);
bool VerifyMessage(byte[] message, byte[] signature);
}
/// <summary>
/// Base58 representation of a pubkey hash and base class for the representation of a script hash
/// </summary>
public class BitcoinPubKeyAddress : BitcoinAddress, IBase58Data, IPubkeyHashUsable
{
public BitcoinPubKeyAddress(string base58, Network expectedNetwork = null)
: base(Validate(base58, ref expectedNetwork), expectedNetwork)
{
var decoded = (expectedNetwork == null ? Encoders.Base58Check : expectedNetwork.NetworkStringParser.GetBase58CheckEncoder()).DecodeData(base58);
_KeyId = new KeyId(new uint160(decoded.Skip(expectedNetwork.GetVersionBytes(Base58Type.PUBKEY_ADDRESS, true).Length).ToArray()));
}
public BitcoinPubKeyAddress(string str, KeyId id, Network expectedNetwork = null)
: base(str, expectedNetwork)
{
if(id == null)
throw new ArgumentNullException(nameof(id));
_KeyId = id;
}
private static string Validate(string base58, ref Network expectedNetwork)
{
if(base58 == null)
throw new ArgumentNullException(nameof(base58));
var networks = expectedNetwork == null ? Network.GetNetworks() : new[] { expectedNetwork };
var data = (expectedNetwork == null ? Encoders.Base58Check : expectedNetwork.NetworkStringParser.GetBase58CheckEncoder()).DecodeData(base58);
foreach(var network in networks)
{
var versionBytes = network.GetVersionBytes(Base58Type.PUBKEY_ADDRESS, false);
if(versionBytes != null && data.StartWith(versionBytes))
{
if(data.Length == versionBytes.Length + 20)
{
expectedNetwork = network;
return base58;
}
}
}
throw new FormatException("Invalid BitcoinPubKeyAddress");
}
public BitcoinPubKeyAddress(KeyId keyId, Network network) :
base(NotNull(keyId) ?? Network.CreateBase58(Base58Type.PUBKEY_ADDRESS, keyId.ToBytes(), network), network)
{
_KeyId = keyId;
}
private static string NotNull(KeyId keyId)
{
if(keyId == null)
throw new ArgumentNullException(nameof(keyId));
return null;
}
public bool VerifyMessage(string message, string signature)
{
var key = PubKey.RecoverFromMessage(message, signature);
return key.Hash == Hash;
}
public bool VerifyMessage(byte[] message, byte[] signature)
{
var key = PubKey.RecoverFromMessage(message, signature);
return key.Hash == Hash;
}
KeyId _KeyId;
public KeyId Hash
{
get
{
return _KeyId;
}
}
public Base58Type Type
{
get
{
return Base58Type.PUBKEY_ADDRESS;
}
}
protected override Script GeneratePaymentScript()
{
return PayToPubkeyHashTemplate.Instance.GenerateScriptPubKey((KeyId)this.Hash);
}
}
}