Bitcoin Forum
April 28, 2024, 05:31:00 AM *
News: Latest Bitcoin Core release: 27.0 [Torrent]
 
   Home   Help Search Login Register More  
Pages: [1]
  Print  
Author Topic: Source code for ECDSA operations in C#  (Read 4728 times)
DeathAndTaxes (OP)
Donator
Legendary
*
Offline Offline

Activity: 1218
Merit: 1079


Gerald Davis


View Profile
April 11, 2014, 03:51:54 PM
Last edit: April 14, 2014, 03:08:53 AM by DeathAndTaxes
 #1

I am looking for a lightweight implementation of basic ECDSA operations, preferably in C#.  If not C# then second choice would be Java (as it can be rather easily be translated to c#) but any language is better than nothing.

I am aware that there is bouncy castle however that is a very heavy interconnected library with lots of complex inheritance which makes parsing out the "necessary bits" probably more of a pain.  I would prefer a simple flat set of minimal classes but even parsing from a lighter library would be a better option.  Yes in general I subscribe to the "never roll your own" theory of development but this is a special case.  A vendor sent me a programmable smartcard development kit for evaluation and it has pretty impressive specs.  Still it is a smartcard so we are talking tens of KB of memory (combined storage and operating memory) so any code is going to need to be scaled down.   SHA-256 (and AES if I wanted to incorporate that for delayed tx signing have hardware support so that is a non-issue.  Rolling an implementation of RIPEMD-160 (thanks mono source code) was rather trivial but ECDSA is a whole different beast.

Bitcoin uses a single static curve (secp256k1) so there is no need for library support for named curves or custom curve params, the secp256k1 parameters coded as constants will work just fine.


Bitcoin addresses contain a checksum, so it is very unlikely that mistyping an address will cause you to lose money.
Advertised sites are not endorsed by the Bitcoin Forum. They may be unsafe, untrustworthy, or illegal in your jurisdiction.
1714282260
Hero Member
*
Offline Offline

Posts: 1714282260

View Profile Personal Message (Offline)

Ignore
1714282260
Reply with quote  #2

1714282260
Report to moderator
1714282260
Hero Member
*
Offline Offline

Posts: 1714282260

View Profile Personal Message (Offline)

Ignore
1714282260
Reply with quote  #2

1714282260
Report to moderator
ning
Full Member
***
Offline Offline

Activity: 173
Merit: 100



View Profile
April 11, 2014, 04:32:44 PM
 #2

I have a homemade Erlang implementation for key generation, signing, and verifying. It's basically a set of functions without any inheritance. The thing is, for your case, it's written in Erlang.
schalk
Newbie
*
Offline Offline

Activity: 36
Merit: 0


View Profile
April 11, 2014, 08:13:46 PM
 #3

I have been in the process of implementing ECDSA using Secp256k1 in C# the last few days. I haven't done much testing yet (still need to write some automated tests!), nor have I had the code reviewed by anyone, so I would strongly advice against using this in production code.

Once I have refactored and tidied up a lot of my code, I plan on creating a github repository for it. I would also still like to make this code more separated with different layers of abstraction to allow for better code testability.

Performance
I haven't done much testing in the way of performance, but I have measured it to be about twice the speed of BouncyCastle.NET on a single thread for EC Multiplication and ECDSA Signing/Verifing. When using multithreading it was an even more significant performance increase in comparison to BouncyCastle.NET (I haven't the figures on me sorry).

A lot of the performance is based on how fast the BigInteger class is. I have been using System.Numerics.BigInteger which is a lot slower than the likes of gmp. One thing to also keep in mind is that unlike BouncyCastle.NET's BigInteger, System.Numerics.BigInteger is Little Endian.

Includes
ECdsaSigner (signing/verification/recovery)
ECELGamal (public/private key encryption - well key generation)
ECEncryption (this is my non standard implementation of encryption with a public key, decryption with a private key. Using AES as the asymmetric cipher and ElGamal as the key generation)
ECPoint (does all your ECPoint math)

Download
https://mega.co.nz/#!Ao1H1IYJ!JgCnLuWhMy0MYrldjV5A4H7pg9seICnJZYIj30Y-eXM

I have also implemented BIP32 (Hierarchical Deterministic Wallets) in a separate project (this uses BouncyCastle), so let me know if you are also in need of that.

If you're feeling a bit generous:
15Xi4QCp9wwbXhCniDB2DkgzLjSw49g619
DeathAndTaxes (OP)
Donator
Legendary
*
Offline Offline

Activity: 1218
Merit: 1079


Gerald Davis


View Profile
April 11, 2014, 09:32:21 PM
 #4

I have a homemade Erlang implementation for key generation, signing, and verifying. It's basically a set of functions without any inheritance. The thing is, for your case, it's written in Erlang.

I would still like to take a look at it if you have the source code available online.
DeathAndTaxes (OP)
Donator
Legendary
*
Offline Offline

Activity: 1218
Merit: 1079


Gerald Davis


View Profile
April 11, 2014, 09:34:00 PM
 #5

I have been in the process of implementing ECDSA using Secp256k1 in C# the last few days. I haven't done much testing yet (still need to write some automated tests!), nor have I had the code reviewed by anyone, so I would strongly advice against using this in production code.

Once I have refactored and tidied up a lot of my code, I plan on creating a github repository for it. I would also still like to make this code more separated with different layers of abstraction to allow for better code testability.

Performance
I haven't done much testing in the way of performance, but I have measured it to be about twice the speed of BouncyCastle.NET on a single thread for EC Multiplication and ECDSA Signing/Verifing. When using multithreading it was an even more significant performance increase in comparison to BouncyCastle.NET (I haven't the figures on me sorry).

A lot of the performance is based on how fast the BigInteger class is. I have been using System.Numerics.BigInteger which is a lot slower than the likes of gmp. One thing to also keep in mind is that unlike BouncyCastle.NET's BigInteger, System.Numerics.BigInteger is Little Endian.

Includes
ECdsaSigner (signing/verification/recovery)
ECELGamal (public/private key encryption - well key generation)
ECEncryption (this is my non standard implementation of encryption with a public key, decryption with a private key. Using AES as the asymmetric cipher and ElGamal as the key generation)
ECPoint (does all your ECPoint math)

Download
https://mega.co.nz/#!Ao1H1IYJ!JgCnLuWhMy0MYrldjV5A4H7pg9seICnJZYIj30Y-eXM

I have also implemented BIP32 (Hierarchical Deterministic Wallets) in a separate project (this uses BouncyCastle), so let me know if you are also in need of that.

If you're feeling a bit generous:
15Xi4QCp9wwbXhCniDB2DkgzLjSw49g619

That is great.  Will take a look at it over the weekend.  If you host it on github I could help out in getting it production ready.
schalk
Newbie
*
Offline Offline

Activity: 36
Merit: 0


View Profile
April 12, 2014, 12:58:35 AM
 #6

Cool, let me know if you have questions.

That would be a great help, it can be quite hard squeezing in time to work on projects like these! I'll flick you a pm once it's on github.
ning
Full Member
***
Offline Offline

Activity: 173
Merit: 100



View Profile
April 12, 2014, 01:32:21 AM
 #7

I have a homemade Erlang implementation for key generation, signing, and verifying. It's basically a set of functions without any inheritance. The thing is, for your case, it's written in Erlang.

I would still like to take a look at it if you have the source code available online.

The verifier is in the public domain (https://github.com/ningzhang/bitcoin-message-verifier). I haven't put up the source code for signing and key generation online, but I can send you a copy later today. Please PM me your email address if you want to take a look at it.
DeathAndTaxes (OP)
Donator
Legendary
*
Offline Offline

Activity: 1218
Merit: 1079


Gerald Davis


View Profile
April 12, 2014, 02:07:41 PM
 #8

Cool, let me know if you have questions.

That would be a great help, it can be quite hard squeezing in time to work on projects like these! I'll flick you a pm once it's on github.

I might have jumped the gun but I got the urge to do some "fun" (non-employment) coding this morning.  To avoid you duplicating a lot of routine housework I threw it up on a quick repo. 
https://github.com/TangibleCryptography/Secp256k1

I did some very basic refactoring (breaking solution into a class library, demo, and testing projections).  Started building out some of the more basic unit tests (hashing & base58 encoding).  I already noticed some issues with signatures.   The signmessage function is returning the compressed key but the signature is based on the uncompressed key.  Most likely we are going to want a keypair class which encapsulates the full bitcoin key "logic" (private key, public key, pubkeyhash, address, etc), that will make it easier to perform signature operations without needing to explicitly ensure compressed vs uncompressed is set properly.  Before I tackle that I will be doing some more basic refactoring to use some c# language features like extension methods.  I used Nunit for testing module and it should pull it directly from Nuget if needed.  I have no problem with Visual Studio internal testing framework (or even Resharper's test framework) but I can't remember which versions of VS don't have testing support.  I figured Nunit might be more open to users of even express version of VS.

Since this is started from your code, if you wish to clone this to your github repo go ahead.  I have no problem taking this down once you have a public copy up. If you want you can give me commit access or if not I can do pull requests from your repo, all depends on how hands on you want to be.  I would recommend adding a license (COPYING) to the root of the repo.  Not sure if you have any preference, if not I am included to use modified BSD (  ).  Lastly the solution is more a lightweight bitcoin crypto library in C#, not just Secp256K1 library, so my boilerplate /Secp256k1 doesn't really describe the scope accurately so it might make sense to change that name of the solution and repo to something more fighting (and less verbose than "lightweight crypto library from bitcoin in C#").


schalk
Newbie
*
Offline Offline

Activity: 36
Merit: 0


View Profile
April 13, 2014, 11:04:08 PM
 #9

Sorry, was just out for the weekend. I was actually at Kim Dotcom's mansion for the Internet Party picnic, it was an amazing weekend. Interestingly the first person I spoke to at the event use to be a developer at MtGox.

Thanks for that, but I will probably put up a repository later this week and I will give you commit access. Smiley just thought it would look good to have something like this on my CV.

Awesome - cheers for that. I have already noted down the issue with returning a compressed key everytime, it's on my mental todo list. Nunit is awesome, my personal preference of a testing framework, what mocking framework do you usually use? I'm quite a fan of Telerik's JustMock.

Yeah, my extensions class is a complete mess at the moment. What's your opinion on extension for strings like HexToBigInteger, HexToBytes and for byte[] ToBigIntegerUnsigned etc? I wasn't sure if those are better kept as static methods or extension methods.

Also, your point about adding in a keypair class. I wasn't too sure about this, I know that the likes of Bitcoinj use this approach. But I was considering maybe separating things out a bit more, having classes like:
PrivateKey - then PrivateKey would have a property called PublicKey
PublicKey - then PublicKey will have a property called PubKeyHash
PubKeyHash - which is essentially the bitcoin address which can be representing with different encoding methods.

I haven't put much thought into the Address class. But I was thinking about maybe making the Address class abstract and having classes like PubKeyHashAddress and ScriptHashAddress inheriting from Address.

What are your thoughts?




DeathAndTaxes (OP)
Donator
Legendary
*
Offline Offline

Activity: 1218
Merit: 1079


Gerald Davis


View Profile
April 14, 2014, 03:38:53 AM
Last edit: April 14, 2014, 09:38:01 PM by DeathAndTaxes
 #10

Awesome - cheers for that. I have already noted down the issue with returning a compressed key everytime, it's on my mental todo list. Nunit is awesome, my personal preference of a testing framework, what mocking framework do you usually use? I'm quite a fan of Telerik's JustMock.

Moq is really the only framework I have used although they are similar enough I don't see that being much of an issue.

Quote
Yeah, my extensions class is a complete mess at the moment. What's your opinion on extension for strings like HexToBigInteger, HexToBytes and for byte[] ToBigIntegerUnsigned etc? I wasn't sure if those are better kept as static methods or extension methods.

The extensions from "true" types/classes is straightforward.  byte[] -> BigInteger, ulong ->VarInt, etc.    The extensions from "psuedo classes" gets a little messier.  Right now "hex" is just a string so having extension methods off of the string class which aren't applicable for non hex strings starts to feel a little kludgy.  On the other hand I am not a fan of the static class with utility methods unless there is no other choice.  I am wondering if a lightweight class for HexString would be a better design choice.

Maybe something like this?
Code:
HexString privHex = new HexString("E9873D79C6D87DC0FB6A5778633389F4453213303DA61F20BD67FC233AA33262");

var aBigInt = privHex.ToBigInteger();
...
Console.WriteLine("Private Key (hex) {0}", privHex.ToString());

Not 100% sure still going back and forth on that one.

Quote
Also, your point about adding in a keypair class. I wasn't too sure about this, I know that the likes of Bitcoinj use this approach. But I was considering maybe separating things out a bit more, having classes like:
PrivateKey - then PrivateKey would have a property called PublicKey
PublicKey - then PublicKey will have a property called PubKeyHash
PubKeyHash - which is essentially the bitcoin address which can be representing with different encoding methods.

Well Address is the versioned and checksummed PubKeyHash.  Still that may work. if a KeyPair class was used I do think it should be lightweight mainly facilitating conversion between the related objects.  I don't like bitcoinj approach on this as it makes the KeyPair (ECKey I believe) class very heavy and there isn't a clear separation of the objects.

Quote
I haven't put much thought into the Address class. But I was thinking about maybe making the Address class abstract and having classes like PubKeyHashAddress and ScriptHashAddress inheriting from Address.

That may work.  The relationships between Bitcoin objects is complex and it makes having clear inheritance "interesting".   To throw a monkey wrench into your structure above keep in mind that WIFPrivateKey, and Addressees are both implementations of the Base58Check structure (version +checksum added to a payload encoded in base58).
doof
Hero Member
*****
Offline Offline

Activity: 765
Merit: 503


View Profile WWW
April 14, 2014, 11:01:27 AM
 #11

Let me know how you get on.  Been doing a lot of c# bitcoin dev.  I'm using bouncy but might be doing a similar thing to you soon.
DeathAndTaxes (OP)
Donator
Legendary
*
Offline Offline

Activity: 1218
Merit: 1079


Gerald Davis


View Profile
April 14, 2014, 03:38:59 PM
 #12

Let me know how you get on.

Not sure what you are asking here.
DeathAndTaxes (OP)
Donator
Legendary
*
Offline Offline

Activity: 1218
Merit: 1079


Gerald Davis


View Profile
April 14, 2014, 09:38:37 PM
 #13

Synced a few commits.  Some basic housekeeping stuff as well as improving VarInt and VarString support.
deepceleron
Legendary
*
Offline Offline

Activity: 1512
Merit: 1028



View Profile WWW
April 16, 2014, 10:34:46 AM
 #14

Let me know how you get on.

Not sure what you are asking here.
Interpretation: "please keep me updated with the progress you are making"
Nicolas Dorier
Hero Member
*****
Offline Offline

Activity: 714
Merit: 619


View Profile
April 20, 2014, 12:52:28 AM
 #15

I don't know if it can help you, but I took the last two week too code a bitcoin port.

You want to sign data ?
var key = new Key();
var sig = key.Sign(data)

you want to verify data ?
key.PubKey.Verify(data,sig)

If you can get ride of BouncyCaslte, please, let me know. (I'm not using tons of stuff of their library, so I guess you can get their source code, recompile the only strict minimum for ECDSA, link NBitcoin to it, and you are good to go)

I coded tons of unit test so you can see if you broke something by doing that.

Github : https://github.com/NicolasDorier/NBitcoin/blob/master/NBitcoin

Bitcoin address 15sYbVpRh6dyWycZMwPdxJWD4xbfxReeHe
Pages: [1]
  Print  
 
Jump to:  

Powered by MySQL Powered by PHP Powered by SMF 1.1.19 | SMF © 2006-2009, Simple Machines Valid XHTML 1.0! Valid CSS!