Closed devssh closed 6 years ago
Is this a feature request?
If so, I think the best option would be to use formats for import / export that are commonly used for cryptographic keys. There's some RFCs on these subjects and openssl
could be a good tool for testing import / export e.g. parsing exported keys with openssl
and importing keys generated by openssl
.
There already exist functions for exporting public and private keys in a way that tools like openssl
understand, fastecdsa.keys.encode_keypair
and fastecdsa.keys.encode_public_key
but they're not robustly tested. Import is still missing, mainly because it requires all sorts of (really fun) ASN.1 parsing. It'll probably get implemented eventually but it's not a high priority for me.
Yes, this is kind of a feature request. Import is quite essential if you are planning on saving the keys or using this in any app that needs to reuse the keys to validate things. The scope of fastecdsa is limited to in-memory use and if an application is stopped all is lost but if import was available it would find a wider audience.
The package is quite well made and I can manage export on my own but the lack of import is kind of a deal breaker.
Would support for import of keys in the form specified in RFC 5915 Elliptic Curve Private Key Structure be sufficient?
Yes, it would be sufficient! Anything easier than having to store the coordinates on the curve, preferably just a path to import keys from a string converted to some format
Commit c2d0bf5 has functionality for import / export, see the following functions in fastecdsa.keys
:
import_key(filepath)
-> returns a (long, fastecdsa.point.Point)
(private_key, public_key) tuple (private_key is None
if you import a public key). filepath
must point to a PEM encoded file e.g. what openssl exports keys as. export_key(key, curve=None, filepath=None)
-> exports a key (either a long
private key or a fastecdsa.point.Point
public key) to the specified filepath
, if none is provided the key is printed to stdout. If a private key is being exported curve
is a required parameter, otherwise the encoding is ambiguous.Let me know if there are any issues, ASN.1 has a million little edge cases that I may have missed in this initial impl.
So can I save it in a human readable compact format like hex(125455157...longnumber)
and then import it! That's nice
I think the import_key
function should take the long
directly, leave the job of reading/parsing the files to others.
Since having to specify the filepath forces it to be in a file
of its own rather than a csv of keys
or database
If you're saving the values in a database or csv I recommend just storing them as hex values, something like:
from binascii import hexlify
private_key_hex = hexlify(private_key)
public_key_x_hex = hexlify(public_key.x)
public_key_y_hex = hexlify(public_key.y)
# now save the hex values to database or to csv
Same goes for reading, just use python builtins to parse the data and then use the Point
constructor to rebuild the public key:
from fastecdsa.point import Point
private_key_hex = # read from DB or csv
public_key_x_hex = # read from DB or csv
public_key_y_hex = # read from DB or csv
private_key = int(private_key_hex, 16)
public_key_x = int(public_key_x_hex, 16)
public_key_y = int(public_key_y_hex, 16)
public_key = Point(public_key_x, public_key_y, curve=...) # fill in whichever curve the key is on
You can also always recover the public key for a private key, so if you store the private key no need store the public key too:
from fastecdsa import keys
private_key_hex = # read from DB or csv
private_key = int(private_key_hex, 16)
public_key = keys.get_public_key(private_key, curve=...) # fill in whichever curve the key is on
No need for special import functions in this case, it's up to you to figure out how to store values in the DB and how to retrieve them and parse them correctly, that's not a job of this library.
No you see, hexlify is sad because we don't need binaries.
The reason we convert the numbers to higher base is to make it more human readable and writable.
So the number 35433438520218993187164445964186767644316745553452984628160110043964158397160
is better read and written as P/a0n.TX{lorxp
Also saving P/a0n.TX{lorxp
also saves space on the database or csv.
Also the int(private_key, 256)
doesn't work and it doesn't work for very long numbers, so python has a problem representing things in higher base in open source.
Base 16 is too small a change, think more like base 256 or 128 to make it intuitive for humans.
At least I can now import the number from the DB, save it as a file and import it using fastecdsa so kudos to that.
Check these to see what I mean Cryptojs Github Google cryptojs
I'm not sure I quite understand. Are you saying you change bases because representations in higher bases take up less space? I suppose this is true if you store the encodings as strings where each character is 8 bits, but the underlying data being represented is the same e.g. the binary data does not change. You're not compressing the data when you switch bases, you're just changing the length of the string encoding the data (since characters in different bases encode different amounts of bits).
So if I get this right you're taking your private key, converting it to binary data, and then encoding that data in base256 to "save space" when storing it? I suppose in that case you'll need to figure out a way to decode base256 strings to binary data in python.
Again, this library isn't really aimed at providing encoding / decoding options (beyond those that are specific to elliptic curve cryptographic keys). This really has nothing to do with any of the topics or functionality the library looks to address. If you want to use exotic encodings not supported by the standard lib best bet would be to write a stand-alone encoder / decoder. As a side note, how are you currently using any of your keys if you don't already have a way of decoding the base256 data that the DB / csv returns to you?
It will still take the same amount of space, whether in binary, encoded string in higher base or decimal.
The difference is that if I can encode it in Base 56, I can easily type the public keys and verify them visually by comparing.
It is always easier to compare character by character a key like rpshnaf39wBU
than 5230453472379659273967392793749372769373927
It's for the human experience and more importantly security verification purposes.
Also keys like 5230453472379659273967392793749372769373927
seem very secure because of how long they are but rpshnaf39wBU
gives a feeling that maybe we should be increasing the characters. It's a bold challenge by the library to increase the bitsize and be performant to scale and deliver in less time. Such stats may encourage more people to use this than write their own code for scalability.
At this point fastecdsa is good for people building production systems to fork and improvise on their own.
But I do get your point in how this feature may not be strictly what the library intends to do, I just pointed out a use case which would speed up adoption
Easy way to do this, with multiple formats like hex