Skip to content

Commit

Permalink
ecdsa
Browse files Browse the repository at this point in the history
  • Loading branch information
kahlys committed Oct 30, 2018
1 parent db80580 commit 7f92f49
Show file tree
Hide file tree
Showing 2 changed files with 129 additions and 0 deletions.
110 changes: 110 additions & 0 deletions ecdsa/ecdsa.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,110 @@
package ecdsa

import (
"crypto/ecdsa"
"encoding/asn1"
"encoding/base64"
"fmt"
"math/big"

"github.com/gopherjs/gopherjs/js"
"github.com/kahlys/webcrypto"
)

func importPrivateKey(prv *ecdsa.PrivateKey) (*js.Object, error) {
jwkKey := js.M{
"kty": "EC",
"crv": prv.Params().Name,
"x": base64.RawURLEncoding.EncodeToString(prv.X.Bytes()),
"y": base64.RawURLEncoding.EncodeToString(prv.Y.Bytes()),
"d": base64.RawURLEncoding.EncodeToString(prv.D.Bytes()),
"ext": true,
}
algorithm := js.M{
"name": "ECDSA",
"namedCurve": prv.Params().Name,
}
return webcrypto.Call("importKey", "jwk", jwkKey, algorithm, false, []string{"sign"})
}

func importPublicKey(pub *ecdsa.PublicKey) (*js.Object, error) {
jwkKey := js.M{
"kty": "EC",
"crv": pub.Params().Name,
"x": base64.RawURLEncoding.EncodeToString(pub.X.Bytes()),
"y": base64.RawURLEncoding.EncodeToString(pub.Y.Bytes()),
"ext": true,
}
algorithm := js.M{
"name": "ECDSA",
"namedCurve": pub.Params().Name,
}
return webcrypto.Call("importKey", "jwk", jwkKey, algorithm, false, []string{"verify"})
}

type ecdsaSignature struct {
R, S *big.Int
}

// Sign calculates the signature of msg using RSASSA-PSS. The opts argument may be nil, in which case sensible
// defaults are used. Warning, msg will be hashed with SHA-256. It returns asn1.encode(r.Bytes(), s.Bytes()).
func Sign(priv *ecdsa.PrivateKey, msg []byte) ([]byte, error) {
privKey, err := importPrivateKey(priv)
if err != nil {
return nil, err
}
hash := js.M{
"name": "SHA-256",
}
algorithm := js.M{
"name": "ECDSA",
"hash": hash,
}
resj, err := webcrypto.Call("sign", algorithm, privKey, msg)
if err != nil {
return nil, err
}
res := js.Global.Get("Uint8Array").New(resj).Interface().([]byte)
order := len(priv.Params().P.Bytes())
r := new(big.Int).SetBytes(res[:order])
s := new(big.Int).SetBytes(res[order:])
return asn1.Marshal(ecdsaSignature{r, s})
}

// Verify verifies the signature sig of msg using the public key pub. A valid signature is
// indicated by returning a nil error.
func Verify(pub *ecdsa.PublicKey, sig, msg []byte) error {
pubKey, _ := importPublicKey(pub)
ss := new(ecdsaSignature)
_, err := asn1.Unmarshal(sig, ss)
if err != nil {
return err
}

// slice size must be group order
ssR, ssS := ss.R.Bytes(), ss.S.Bytes()
order := len(pub.Params().P.Bytes())
for len(ssR) < order {
ssR = append([]byte{0}, ssR...)
}
for len(ssS) < order {
ssS = append([]byte{0}, ssS...)
}
theSig := append(ssR, ssS...)

hash := js.M{
"name": "SHA-256",
}
algorithm := js.M{
"name": "ECDSA",
"hash": hash,
}
resj, err := webcrypto.Call("verify", algorithm, pubKey, theSig, msg)
if err != nil {
return err
}
if !resj.Bool() {
return fmt.Errorf("verification error")
}
return nil
}
19 changes: 19 additions & 0 deletions test/test.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,14 @@ package main

import (
"bytes"
"crypto/ecdsa"
"crypto/elliptic"
"crypto/rand"
"encoding/hex"
"fmt"

"github.com/kahlys/webcrypto/aes"
wecdsa "github.com/kahlys/webcrypto/ecdsa"
"github.com/kahlys/webcrypto/sha"
)

Expand Down Expand Up @@ -101,6 +105,20 @@ func testAesGcm() error {
return nil
}

func testEcdsa() error {
text := []byte("yellow submarine")
priv, _ := ecdsa.GenerateKey(elliptic.P256(), rand.Reader)
sig, err := wecdsa.Sign(priv, text)
if err != nil {
return fmt.Errorf("unable to sign: %v", err)
}
err = wecdsa.Verify(&priv.PublicKey, sig, text)
if err != nil {
return fmt.Errorf("unable to verify: %v", err)
}
return nil
}

func main() {
register(
testfunc{"SHA-1", testSha1},
Expand All @@ -109,6 +127,7 @@ func main() {
testfunc{"SHA-512", testSha512},
testfunc{"AES-CBC", testAesCbc},
testfunc{"AES-GCM", testAesGcm},
testfunc{"ECDSA", testEcdsa},
)
run()
}
Expand Down

0 comments on commit 7f92f49

Please sign in to comment.