Skip to content

Instantly share code, notes, and snippets.

@shibumi
Created July 29, 2020 21:58
Show Gist options
  • Save shibumi/f25d1b7a2a3d5f0f85bb0530bed7802d to your computer and use it in GitHub Desktop.
Save shibumi/f25d1b7a2a3d5f0f85bb0530bed7802d to your computer and use it in GitHub Desktop.
This code is a proof of concept for showing, that r and s may have different length for Go's crypto/ecdsa library
package main
import (
"crypto/ecdsa"
"crypto/elliptic"
"crypto/rand"
"crypto/sha256"
"encoding/hex"
"fmt"
"math/big"
)
// This code is a proof of concept for showing, that r and s may have different length
// and therefore leading to a signature validation fail.
// Copy this code onto your machine and run it with: `while true; do go run ./main.go; done`
// Then wait... if nothing happens, try making your CPU as busy as possible
func main() {
var signatureBuffer []byte
privKey, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader)
if err != nil {
fmt.Println(err)
}
data := `{"_type":"link","byproducts":{},"command":[],"environment":{},"materials":{},"name":"foo","products":{}}`
hashed := sha256.Sum256([]byte(data))
r, s, err := ecdsa.Sign(rand.Reader, privKey, hashed[:])
if err != nil {
fmt.Println(err)
}
signatureBuffer = append(signatureBuffer, r.Bytes()...)
signatureBuffer = append(signatureBuffer, s.Bytes()...)
signature := hex.EncodeToString(signatureBuffer)
sigBytes, err := hex.DecodeString(signature)
if err != nil {
fmt.Println(err)
}
rsSize := len(sigBytes) / 2
rNew := new(big.Int)
sNew := new(big.Int)
rNew.SetBytes(sigBytes[:rsSize])
sNew.SetBytes(sigBytes[rsSize:])
if err := ecdsa.Verify(privKey.Public().(*ecdsa.PublicKey), hashed[:], rNew, sNew); err == false {
fmt.Printf("r bytes length: %d\n", len(r.Bytes()))
fmt.Printf("s bytes length: %d\n", len(s.Bytes()))
fmt.Println("invalid")
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment