I have a struct Transaction
with the following fields,
type Transaction struct {
Sender string `json:"sender"`
Receiver string `json:"receiver"`
Signature string `json:"signature"`
Amount int64 `json:"amount"`
}
I also have a function GetPrivateKey()
which returns a *rsa.PrivateKey
func GetPrivateKey() (*rsa.PrivateKey, error) {
key, err := ioutil.ReadFile("/Users/xxx/.ssh/id_rsa")
if err != nil {
return nil, err
}
block, _ := pem.Decode(key)
der, err := x509.ParsePKCS1PrivateKey(block.Bytes)
if err != nil {
return nil, err
}
return der, err
}
My plan here is to sign the contents of the struct transaction
using a private key already in the system and then store it as a string in the field signature
in the struct, For this, I have a function SignPayload()
func SignPayload(txnObj *Transaction) error {
privateKey, err := GetPrivateKey()
if err != nil {
panic(err)
}
bodyHash, err := rsa.SignPKCS1v15(rand.Reader, privateKey,
crypto.SHA256, []byte(fmt.Sprintf("%v", *txnObj)))
if err != nil {
panic(err)
}
txnObj.Signature = string(bodyHash)
log.Println(txnObj.Signature)
return err
}
Unfortunately, this is not working,rsa.SignPKCS1v15()
throws an error saying:
crypto/rsa: input must be hashed message
The end goal here is to use this signature to verify the authenticity of the struct by comparing it with the public key present in the field sender
.
I'm an absolute newbie in cryptography, What am I doing wrong here? and more importantly, How can I do this?
Thanks in advance!
Two things here:
rsa.SignPKCS1v15
expects a message length matching the hash algorithm's output (256 bits, or 32 bytes for sha-256)%v
representation of your struct, serialize it insteadThe first is spelled out in the rsa docs. Given a message, you can sign it using the following:
message := []byte("message to be signed")
hashed := sha256.Sum256(message)
signature, err := rsa.SignPKCS1v15(rand.Reader, privateKey, crypto.SHA256, hashed[:])
if err != nil {
panic(err)}
}
The second point is more about making your code more robust. You don't want a change in %v
logic or addition of non-exported fields to cause issues. You may also want to check the signature from a language other than Go.
Thus, you should first marshal your struct. You already have json tags on it, so it's fairly easy:
message, err := json.Marshal(txnObj)
if err != nil {
panic(err)
}
Message is the byte slice passed to sha256.Sum256
above.
When verifying the signature, you'll need to make sure to zero out the Signature
field of your struct, marshal it, hash it, and call rsa.VerifyPKCS1v15
.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With