using Org.BouncyCastle.Asn1;
using Org.BouncyCastle.Asn1.Nist;
using Org.BouncyCastle.Asn1.Sec;
using Org.BouncyCastle.Asn1.X9;
using Org.BouncyCastle.Crypto.Parameters;
using Org.BouncyCastle.Crypto.Signers;
using Org.BouncyCastle.Math;
using Org.BouncyCastle.Math.EC;
using Org.BouncyCastle.Security.Certificates;
using Org.BouncyCastle.Security;
using Org.BouncyCastle.Utilities.Encoders;
using System.Security.Cryptography;
using System.Security.Cryptography.X509Certificates;
using Org.BouncyCastle.Asn1.Ocsp;
public static BigInteger Parse(string value, int radix, string digits)
if ((radix > digits.Length) || (radix < 2))
throw new ArgumentOutOfRangeException("radix", radix,
string.Format("Radix has to be within range <2, {0}>;", digits.Length));
value = digits.Substring(0, 1);
BigInteger RetValue = BigInteger.Zero;
for (int i = 0; i < value.Length; i++)
int CharIdx = digits.IndexOf(value[i]);
if ((CharIdx >= radix) || (CharIdx < 0))
throw new ArgumentOutOfRangeException("Value", digits[CharIdx], "Invalid character in the input string.");
RetValue = RetValue.Multiply(BigInteger.ValueOf(radix)).Add(BigInteger.ValueOf(CharIdx));
public static void Main()
string base32Sign = "61204819ISU8CR5CH50PJ500RQRN21GM4F7ML5MTQ64BEI2D20MVB3C4AG12022JEV65AJIQUD1OJN4451J3RULI6UPS2L2F256NSSPQR1THKK4E";
string data = "ETD*1*IN:DPP*TT:PASS*X-DEV:3BFA09325044BFFC134483872D6EBABE*X-ACC:1253315*";
string pub = "04a15d1da838d55dfd0979c399fef3d73b17f025c0aa82c80f972440dc79128d3ae0f7e90807e1b7232694d11f3180734bbd75585764e231520e811ad5c62f224d";
string sig = BitConverter.ToString(Parse(base32Sign, 32, "0123456789ABCDEFGHIJKLMNOPQRSTUV").ToByteArray()).Replace("-", "");
Console.WriteLine("sig");
Console.WriteLine("3044022029973C866CAC8941999400DEB771061623CF6A96DDD188B7484D102DF58D84540220085377CC554E5AF34389DC8428663DFAB237B3C1544F114D7E733AD87B1A508E");
Console.WriteLine("Message");
var msg = Encoding.UTF8.GetBytes(data);
Console.WriteLine(BitConverter.ToString(msg).Replace("-", ""));
msg = Convert( "4554442A312A494E3A4450502A54543A504153532A582D4445563A33424641303933323530343442464643313334343833383732443645424142452A582D4143433A313235333331352A");
Console.WriteLine(BitConverter.ToString(msg).Replace("-", ""));
Console.WriteLine("result (EccVerifyMessage): " + EccVerifyMessage(msg, Convert(sig), Convert(pub)));
Console.WriteLine("result (VerifySignature): " + VerifySignature(msg, pub, sig));
static bool EccVerifyMessage(byte[] message, byte[] signature, byte[] pubkey)
Console.WriteLine("XMSG: " + BitConverter.ToString(message).Replace("-", ""));
Console.WriteLine("XSIG: " + BitConverter.ToString(signature).Replace("-", ""));
Console.WriteLine("XPUB: " + BitConverter.ToString(pubkey).Replace("-", ""));
BigInteger x = new BigInteger(1, pubkey.Skip(1).Take(32).ToArray());
BigInteger y = new BigInteger(1, pubkey.Skip(33).ToArray());
X9ECParameters ecParams = NistNamedCurves.GetByName("P-256");
ECDomainParameters domainParameters = new ECDomainParameters(ecParams.Curve, ecParams.G, ecParams.N, ecParams.H, ecParams.GetSeed());
Org.BouncyCastle.Math.EC.ECCurve curve = ecParams.Curve;
Org.BouncyCastle.Math.EC.ECPoint q = curve.CreatePoint(x, y);
ECPublicKeyParameters pubkeyParam = new ECPublicKeyParameters(q, domainParameters);
Console.WriteLine("XXX: " + pubkeyParam.ToString());
var verifier = SignerUtilities.GetSigner("SHA256withECDSA");
verifier.Init(false, pubkeyParam);
verifier.BlockUpdate(message, 0, message.Length);
return verifier.VerifySignature(signature);
public static bool VerifySignature(byte[] message, string publicKey, string signature)
var curve = SecNamedCurves.GetByName("secp256r1");
var domain = new ECDomainParameters(curve.Curve, curve.G, curve.N, curve.H);
var publicKeyBytes = Convert(publicKey);
var q = curve.Curve.DecodePoint(publicKeyBytes);
var keyParameters = new ECPublicKeyParameters(q, domain);
var verifier = new ECDsaSigner();
verifier.Init(false, keyParameters);
Asn1InputStream decoder = new Asn1InputStream(Convert(signature));
DerSequence seq = (DerSequence)decoder.ReadObject();
var rp = r.PositiveValue;
var sp = s.PositiveValue;
var sha256= SHA256.Create().ComputeHash(message);
return verifier.VerifySignature(sha256, rp, sp);
public static byte[] Convert(string input)
if (input.StartsWith("0x")) input = input.Remove(0, 2);
return Enumerable.Range(0, input.Length / 2).Select(x => System.Convert.ToByte(input.Substring(x * 2, 2), 16)).ToArray();