Not sure how to generate an ECDSA signature, given a private key and a message

ぃ、小莉子 提交于 2019-12-22 07:36:37

问题


I'm following Apple's guide towards composing a CloudKit Web Services request. The bit I'm having trouble with is Step 2, under "Authenticate Web Service Requests":

  1. Compute the ECDSA signature of this message with your private key.

Before getting to this point, I generated my certificate, a .pem file, which when opening it in a text editor shows me my private key, so I have that in string format too.

I've also followed the steps for generating what it refers to as a message, which I now have as a string.

So given that I have a private key, (or the .pem file if required), and a message as a string, it should in theory be fairly simple for me to get a ECDSA signature of the message, computed with my private key. But here's where I'm struggling. Libraries that I've found online seem to take a far more complicated approach, with different moving parts, no reference to a .pem file and talk of generating new public/private keys.

Any help with this step would be greatly appreciated.


回答1:


It appears that the documentation and the actual API for Ruby’s OpenSSL EC support are both currently rather lacking. In particular, in Ruby <= 2.3.1 the OpenSSL::PKey::EC doesn’t follow the same API as RSA and DSA keys for signing and verifying. What you would want to do, but currently can’t with EC keys, is this (all the code here assumes you have called require 'openssl' somewhere):

# Get the key, here I'm reading the file
priv_key = OpenSSL::PKey.read(File.read('eckey.pem')) 

# This should be the appropriately formatted string
data = "some data to sign"

# The hash algorithm, I assume SHA256 is being used
digest = OpenSSL::Digest::SHA256.new

# This doesn't work in 2.3.1, but does in 2.4.0-preview1
signature = priv_key.sign(digest, data)

As I note in the comments, this does work in Ruby 2.4.0-preview1, but that’s likely not much use to you.

To get it working with current Ruby, you need to do something like this:

# As before:
priv_key = OpenSSL::PKey.read(File.read('eckey.pem'))
data = "some data to sign"

signature = priv_key.dsa_sign_asn1(OpenSSL::Digest::SHA256.digest(data))

Both these techniques give you a binary string. I think you will need to base64 encode it before adding it as your request header.

To extract the public key to check the signature verifies is also a bit tricky (although you could just use the openssl command line and read in the file). The public_key methods returns an OpenSSL::PKey::EC::Point object rather than an actual key, so we need to recreate one from the private key. The verify method does work on Ruby 2.3.1:

pub = OpenSSL::PKey::EC.new(priv_key.group)
pub.public_key = priv_key.public_key

data = "some data to sign"
digest = OpenSSL::Digest::SHA256.new

puts pub.verify(digest, sig, data)

The Apple page doesn’t appear to specify the hash algorithm to use, but from what I’ve seen it looks like SHA-256 is right. (Also I could have got this completely wrong and Apple are using a completely different format. I’d be keen to know whether or not this code works you you).



来源:https://stackoverflow.com/questions/38934615/not-sure-how-to-generate-an-ecdsa-signature-given-a-private-key-and-a-message

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!