2013-04-12 75 views
2

项目https://github.com/Bitmessage/PyBitmessage使用库文件https://github.com/yann2192/pyelliptic用于openssl。转换Python(pyelliptic,openssl)ecc key并签名到c#(BouncyCastle?)

pyelliptic测试用例:

#!/usr/bin/python 
import pyelliptic 
from pyelliptic import arithmetic as a 

#privkey = a.changebase('02ca0020215c5516f277ac6246cbbaad81cd848328bf9bf11e98959e2b991191a71ad81a',16,256) 
pubkey = a.changebase('02ca0020012e0e59b564c025b15a587da5d33d3599df5e04deca47c783eaed25ebe5af46002032e00af993efc71a2c033a45187918f5b3c03e0e7bb539cecdc0aaa237717db1',16,256) 
signature = a.changebase('30450221008538ac52dbe2b67148e99f23ad78b4c6c4939a26d789ece590c6f1e44a271454022027d4a09e5e74bb3445019a557bd2202154d2510a4df939b9f4645b311255ee37',16,256) 

ecc = pyelliptic.ECC(curve='secp256k1',pubkey=pubkey) 
print ecc.verify(signature,'hello') 

I端口PyBitmessage到c#https://github.com/sharpbitmessage/SharpBitmessage/。对于openssl,我使用BouncyCastle。

我的测试用例(虚开):

using System; 
using System.Text; 
using Org.BouncyCastle.Asn1; 
using Org.BouncyCastle.Asn1.Sec; 
using Org.BouncyCastle.Asn1.X9; 
using Org.BouncyCastle.Crypto.Parameters; 
using Org.BouncyCastle.Crypto.Signers; 
using Org.BouncyCastle.Utilities.Encoders; 

namespace ConsoleApplication2 
{ 
internal class Program 
{ 
    //private static readonly byte[] _privkey = "02ca0020215c5516f277ac6246cbbaad81cd848328bf9bf11e98959e2b991191a71ad81a".HexToBytes(); 
    private static readonly byte[] _pubkey = 
     Hex.Decode(
      "02ca0020012e0e59b564c025b15a587da5d33d3599df5e04deca47c783eaed25ebe5af46002032e00af993efc71a2c033a45187918f5b3c03e0e7bb539cecdc0aaa237717db1"); 

    private static readonly byte[] _signature = 
     Hex.Decode(
      "30450221008538ac52dbe2b67148e99f23ad78b4c6c4939a26d789ece590c6f1e44a271454022027d4a09e5e74bb3445019a557bd2202154d2510a4df939b9f4645b311255ee37"); 

    private static readonly byte[] _hello = Encoding.ASCII.GetBytes("hello"); 

    private static byte[] ConvertKeyFormat(byte[] k) 
    { 
     // convert key to 04012e0e59b564c025b15a587da5d33d3599df5e04deca47c783eaed25ebe5af4632e00af993efc71a2c033a45187918f5b3c03e0e7bb539cecdc0aaa237717db1 
     byte[] result = new byte[k.Length-4+1-2]; 
     result[0] = 4; 
     Buffer.BlockCopy(k,4  ,result,1 ,32); 
     Buffer.BlockCopy(k,4+32+2,result,33,32); 
     return result; 
    } 

    private static void Main() 
    { 
     var signer = new ECDsaSigner(); 

     X9ECParameters secp256K1 = SecNamedCurves.GetByName("secp256k1"); 
     ECDomainParameters ecParams = new ECDomainParameters(secp256K1.Curve, secp256K1.G, secp256K1.N, secp256K1.H); 
     ECPublicKeyParameters param = new ECPublicKeyParameters(ecParams.Curve.DecodePoint(ConvertKeyFormat(_pubkey)), ecParams); 

     signer.Init(false, param); 

     DerSequence seq = (DerSequence)(new Asn1InputStream(_signature)).ReadObject(); 
     DerInteger r = (DerInteger)seq[0]; 
     DerInteger s = (DerInteger)seq[1]; 

     Console.WriteLine(signer.VerifySignature(_hello, r.Value, s.Value)); 
    } 
} 
} 

如何从pyelliptic在C#中验证签名?

回答

0

我拒绝BouncyCastle赞成OpenSSL。下面

工作码(注释是从pyelliptic Python代码):

using System; 
using System.Text; 
using OpenSSL.Core; // I get Native.cs from http://openssl-net.sourceforge.net/ 
using Org.BouncyCastle.Utilities.Encoders; // only for Hex.Decode 

namespace openssl 
{ 
class Program 
{ 
    private static readonly byte[] _signature = 
     Hex.Decode(   "30450221008538ac52dbe2b67148e99f23ad78b4c6c4939a26d789ece590c6f1e44a271454022027d4a09e5e74bb3445019a557bd2202154d2510a4df939b9f4645b311255ee37"); 

    private static readonly byte[] _hello = Encoding.ASCII.GetBytes("hello"); 

    static void Main(string[] args) 
    { 
//curve = pubkey[0:2])[0]      !!! 714 
//tmplen1 = unpack('!H', pubkey[2:4])[0]   !!! 32 
//pubkey_x = pubkey[4:4 + tmplen1] 
//tmplen2 = unpack('!H', pubkey[4 + tmplen1:4 + tmplen1 + 2])[0] 
//pubkey_y = pubkey[4 + tmplen1 + 2:4 + tmplen1 + 2 + tmplen2] 

    //private static readonly byte[] _pubkey = 
    // Hex.Decode(
    //  "02ca" + 
    //  "0020" + 
    //  "012e0e59b564c025b15a587da5d33d3599df5e04deca47c783eaed25ebe5af46" + !!!!! 
    //  "0020" + 
    //  "32e00af993efc71a2c033a45187918f5b3c03e0e7bb539cecdc0aaa237717db1"); !!!!! 

     string pubkey_x = "012e0e59b564c025b15a587da5d33d3599df5e04deca47c783eaed25ebe5af46"; 
     string pubkey_y = "32e00af993efc71a2c033a45187918f5b3c03e0e7bb539cecdc0aaa237717db1"; 

//digest = OpenSSL.malloc(0, 64) 
//dgst_len = OpenSSL.pointer(OpenSSL.c_int(0)) 
     byte[] digest = new byte[64]; 
     uint dgst_len = 0; 

//key = OpenSSL.EC_KEY_new_by_curve_name(curve) 
//if key == 0: 
// raise Exception("[OpenSSL] EC_KEY_new_by_curve_name FAIL ...") 
     IntPtr key = Native.EC_KEY_new_by_curve_name(714); 

//pub_key_x = OpenSSL.BN_bin2bn(pubkey_x, len(pubkey_x), 0) 
//pub_key_y = OpenSSL.BN_bin2bn(pubkey_y, len(pubkey_y), 0) 

     IntPtr pub_key_x; 
     Native.BN_hex2bn(out pub_key_x, Encoding.ASCII.GetBytes(pubkey_x)); 

     IntPtr pub_key_y; 
     Native.BN_hex2bn(out pub_key_y, Encoding.ASCII.GetBytes(pubkey_y)); 

//group = OpenSSL.EC_KEY_get0_group(key) 
     IntPtr group = Native.EC_KEY_get0_group(key); 
//pub_key = OpenSSL.EC_POINT_new(group) 
     IntPtr pub_key = Native.EC_POINT_new(group); 

//if (OpenSSL.EC_POINT_set_affine_coordinates_GFp(group, pub_key, pub_key_x, pub_key_y, 0)) == 0:  !!!!!!!!! 
// raise Exception("[OpenSSL] EC_POINT_set_affine_coordinates_GFp FAIL ...") 
     if(Native.EC_POINT_set_affine_coordinates_GFp(group, pub_key, pub_key_x, pub_key_y, IntPtr.Zero)==0) 
      throw new Exception("[OpenSSL] EC_POINT_set_affine_coordinates_GFp FAIL ..."); 

//if (OpenSSL.EC_KEY_set_public_key(key, pub_key)) == 0: 
// raise Exception("[OpenSSL] EC_KEY_set_public_key FAIL ...") 
     if (Native.EC_KEY_set_public_key(key, pub_key) == 0) 
      throw new Exception("[OpenSSL] EC_KEY_set_public_key FAIL ..."); 

//if (OpenSSL.EC_KEY_check_key(key)) == 0: 
// raise Exception("[OpenSSL] EC_KEY_check_key FAIL ...") 
     if (Native.EC_KEY_check_key(key) == 0) 
      throw new Exception("[OpenSSL] EC_KEY_check_key FAIL ..."); 

//md_ctx = OpenSSL.EVP_MD_CTX_create() 
     var md_ctx = Native.EVP_MD_CTX_create(); 
//OpenSSL.EVP_MD_CTX_init(md_ctx) 
     Native.EVP_MD_CTX_init(md_ctx); 
//OpenSSL.EVP_DigestInit(md_ctx, OpenSSL.EVP_ecdsa()) 
     Native.EVP_DigestInit_ex(md_ctx, Native.EVP_ecdsa(), IntPtr.Zero); 
//if (OpenSSL.EVP_DigestUpdate(md_ctx, inputb, len(inputb))) == 0: 
// raise Exception("[OpenSSL] EVP_DigestUpdate FAIL ...") 
     if (Native.EVP_DigestUpdate(md_ctx, _hello, (uint)_hello.Length)==0) 
      throw new Exception("[OpenSSL] EVP_DigestUpdate FAIL ..."); 
//OpenSSL.EVP_DigestFinal(md_ctx, digest, dgst_len) 
     Native.EVP_DigestFinal_ex(md_ctx, digest, ref dgst_len); 

//ret = OpenSSL.ECDSA_verify(0, digest, dgst_len.contents, sig, len(sig), key) 
     //key.Verify(null, _signature); 
     int ret = Native.ECDSA_verify(0, digest, (int) dgst_len, _signature, _signature.Length, key); 

     Console.WriteLine(ret == 1); 

     Console.ReadKey(); 

     // todo free memory from openssl resource!!! 
    } 
} 

}