我知道可以使用Regex(^[13][a-km-zA-HJ-NP-Z0-9]{26,33}$
)验证比特币钱包地址 - 但这不是100%准确,并且允许无效地址被检测为有效。
是否有公开的C#算法可以验证比特币钱包地址?我一直在谷歌搜索,但找不到任何东西。
答案 0 :(得分:3)
是的,Bitcoin-Address-Utility项目是一个包含此类验证的开源C#工具。请特别注意Casascius.Bitcoin.Util.Base58CheckToByteArray()
。
答案 1 :(得分:3)
我拼凑了一个简单版本的Casascius.Bitcoin.Util.Base58CheckToByteArray(),它与dotnet core 2.0一起使用 - 唯一的参考是 - > Org.BouncyCastle.Crypto.Digests;
public class Validator
{
public static bool IsValidAddress(string Address)
{
byte[] hex = Base58CheckToByteArray(Address);
if (hex == null || hex.Length != 21)
return false;
else
return true;
}
public static byte[] Base58CheckToByteArray(string base58)
{
byte[] bb = Base58.ToByteArray(base58);
if (bb == null || bb.Length < 4) return null;
Sha256Digest bcsha256a = new Sha256Digest();
bcsha256a.BlockUpdate(bb, 0, bb.Length - 4);
byte[] checksum = new byte[32];
bcsha256a.DoFinal(checksum, 0);
bcsha256a.BlockUpdate(checksum, 0, 32);
bcsha256a.DoFinal(checksum, 0);
for (int i = 0; i < 4; i++)
{
if (checksum[i] != bb[bb.Length - 4 + i]) return null;
}
byte[] rv = new byte[bb.Length - 4];
Array.Copy(bb, 0, rv, 0, bb.Length - 4);
return rv;
}
}
} - 从上面借来
public class Base58
{
/// <summary>
/// Converts a base-58 string to a byte array, returning null if it wasn't valid.
/// </summary>
public static byte[] ToByteArray(string base58)
{
Org.BouncyCastle.Math.BigInteger bi2 = new Org.BouncyCastle.Math.BigInteger("0");
string b58 = "123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz";
foreach (char c in base58)
{
if (b58.IndexOf(c) != -1)
{
bi2 = bi2.Multiply(new Org.BouncyCastle.Math.BigInteger("58"));
bi2 = bi2.Add(new Org.BouncyCastle.Math.BigInteger(b58.IndexOf(c).ToString()));
}
else
{
return null;
}
}
byte[] bb = bi2.ToByteArrayUnsigned();
// interpret leading '1's as leading zero bytes
foreach (char c in base58)
{
if (c != '1') break;
byte[] bbb = new byte[bb.Length + 1];
Array.Copy(bb, 0, bbb, 1, bb.Length);
bb = bbb;
}
return bb;
}
public static string FromByteArray(byte[] ba)
{
Org.BouncyCastle.Math.BigInteger addrremain = new Org.BouncyCastle.Math.BigInteger(1, ba);
Org.BouncyCastle.Math.BigInteger big0 = new Org.BouncyCastle.Math.BigInteger("0");
Org.BouncyCastle.Math.BigInteger big58 = new Org.BouncyCastle.Math.BigInteger("58");
string b58 = "123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz";
string rv = "";
while (addrremain.CompareTo(big0) > 0)
{
int d = Convert.ToInt32(addrremain.Mod(big58).ToString());
addrremain = addrremain.Divide(big58);
rv = b58.Substring(d, 1) + rv;
}
// handle leading zeroes
foreach (byte b in ba)
{
if (b != 0) break;
rv = "1" + rv;
}
return rv;
}
}
} - 测试
[TestClass]
public class ValidatorTests
{
[TestMethod]
public void IsValidAddress_Test_AbnCoin()
{
var Address = "1QF4NgxgF86SH4dizN4JPHMprWBHbKdSmJ";
Assert.IsTrue(Validator.IsValidAddress(Address));
}
[TestMethod]
public void IsValidAddress_Test_BitCoin()
{
var Address = "1QF4NgxgF86SH4dizN4JPHMprWBHbKdSmJ";
Assert.IsTrue(Validator.IsValidAddress(Address));
}
[TestMethod]
public void IsValidAddress_Test_BitCoinTestnet()
{
var Address = "mpMwtvqaLQ4rCJsnoceAoLShKb4inV8uUi";
Assert.IsTrue(Validator.IsValidAddress(Address));
}
[TestMethod]
public void IsValidAddress_Test_BitCoinGold()
{
var Address = "GRiDm3LEjXAMMJhWaYqN8nSjuU7PSqZMUe";
Assert.IsTrue(Validator.IsValidAddress(Address));
}
[TestMethod]
public void IsValidAddress_Test_Dash()
{
var Address = "Xb9Edf28eYR9RRDwj7MBBVBc5vgGgT2vLV";
Assert.IsTrue(Validator.IsValidAddress(Address));
}
[TestMethod]
public void IsValidAddress_Test_Litecoin()
{
var Address = "LUdpZosHDP3M97ZSfvj3p1qygNFMNpXBr3";
Assert.IsTrue(Validator.IsValidAddress(Address));
}
[TestMethod]
public void IsValidAddress_Test_False_TooShort()
{
var Address = "1QF4NgxgF86SH4dizN4JPHMprWBHbKdSm";
Assert.IsFalse(Validator.IsValidAddress(Address));
}
[TestMethod]
public void IsValidAddress_Test_False_TooLong()
{
var Address = "1QF4NgxgF86SH4dizN4JPHMprWBHbKdSmJS";
Assert.IsFalse(Validator.IsValidAddress(Address));
}
[TestMethod]
public void IsValidAddress_Test_False_BadChecksum()
{
var Address = "1QF5NgxgF86SH4dizN4JPHMprWBHbKdSmJ";
Assert.IsFalse(Validator.IsValidAddress(Address));
}
[TestMethod]
public void IsValidAddress_False_NotBase58()
{
var Address = "lQF4NgxgF86SH4dizN4JPHMprWBHbKdSmJ";
Assert.IsFalse(Validator.IsValidAddress(Address));
}
}
}
答案 2 :(得分:1)
tl; dr: 遇到同样的问题,因此构建了一些适合我(并希望您)需要的东西: https://github.com/Sofoca/CoinUtils
我的具体要求是……
虽然以上提到的替代方法都无法满足我的所有需求,但我从先前的答案和参考项目中获得了一些启发。谢谢你!
希望这对那些寻求完整但轻便的解决方案的人有所帮助。
答案 3 :(得分:0)
代码是从其他答案引用的Bitcoin-Address-Utility project中提取的,但是此存储库包含必需的DLL,而且它是类项目而不是Windows应用程序,因此可以直接引用它。