Skip to content

Commit

Permalink
refactor(#29): updated readme, added examples, minor fixes
Browse files Browse the repository at this point in the history
  • Loading branch information
stevencedro committed Apr 14, 2024
1 parent bd5a97b commit 35ae19c
Show file tree
Hide file tree
Showing 6 changed files with 268 additions and 15 deletions.
15 changes: 15 additions & 0 deletions .vscode/launch.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
{
// Use IntelliSense to learn about possible attributes.
// Hover to view descriptions of existing attributes.
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
"version": "0.2.0",
"configurations": [
{
"name": "hmac",
"type": "go",
"request": "launch",
"mode": "auto",
"program": "examples/hmac/main.go"
}
]
}
46 changes: 35 additions & 11 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ See specific algorithms for the parameter types to be passed in.

The **ECDSA** algorithm is the implementation of operations described in [§23](https://www.w3.org/TR/WebCryptoAPI/#ecdsa) of the W3C specification.

`import "github.com/armortal/webcrypto-go/algorithms/ecdsa"`.
`import "github.com/armortal/webcrypto-go/algorithms/ecdsa"`

#### Parameter Definitions

Expand Down Expand Up @@ -102,6 +102,8 @@ As specified in [§23.6](https://www.w3.org/TR/WebCryptoAPI/#EcKeyImportParams-d
package main

import (
"fmt"

"github.com/armortal/webcrypto-go"
"github.com/armortal/webcrypto-go/algorithms/ecdsa"
)
Expand All @@ -123,15 +125,15 @@ func main() {
}

// key returned is a webcrypto.CryptoKeyPair
ckp := key.(webcrypto.CryptoKeyPair)
cryptoKey := key.(webcrypto.CryptoKeyPair)

// sign some data with the private key
sig, err := webcrypto.Subtle().Sign(&webcrypto.Algorithm{
Name: "ECDSA",
Params: &ecdsa.Params{
Hash: "SHA-256",
},
}, ckp.PrivateKey(), []byte("test"))
}, cryptoKey.PrivateKey(), []byte("test"))
if err != nil {
panic(err)
}
Expand All @@ -142,27 +144,48 @@ func main() {
Params: &ecdsa.Params{
Hash: "SHA-256",
},
}, ckp.PublicKey(), sig, []byte("test"))
}, cryptoKey.PublicKey(), sig, []byte("test"))
if err != nil {
panic(err)
}

if !ok {
// didn't verify - do something
panic("signature didn't verify")
}

// export the public/private key as webcrypto.JsonWebKey
out, err := webcrypto.Subtle().ExportKey(webcrypto.Jwk, ckp.PrivateKey())
out, err := webcrypto.Subtle().ExportKey(webcrypto.Jwk, cryptoKey.PrivateKey())
if err != nil {
panic(err)
}

jwk := out.(webcrypto.JsonWebKey)

// do something with jwk
jwk := out.(*webcrypto.JsonWebKey)

// export the key as PKCS8
out, err = webcrypto.Subtle().ExportKey(webcrypto.PKCS8, cryptoKey.PrivateKey())
if err != nil {
panic(err)
}

// do something with the pkcs8 key
pkcs8 := out.([]byte)

// import a public/private key from a jwk
in, err := webcrypto.Subtle().ImportKey(webcrypto.Jwk, jwk, &webcrypto.Algorithm{
Name: "ECDSA",
Params: &ecdsa.KeyImportParams{
NamedCurve: "P-256",
},
}, true, []webcrypto.KeyUsage{
webcrypto.Sign,
})
if err != nil {
panic(err)
}

// import a public/private key
ck, err := webcrypto.Subtle().ImportKey(webcrypto.Jwk, jwk, &webcrypto.Algorithm{
// import a public/private key from PKCS8
in, err = webcrypto.Subtle().ImportKey(webcrypto.PKCS8, pkcs8, &webcrypto.Algorithm{
Name: "ECDSA",
Params: &ecdsa.KeyImportParams{
NamedCurve: "P-256",
Expand All @@ -175,14 +198,15 @@ func main() {
}

// do something with the imported webcrypto.CryptoKey
fmt.Println(in.Type())
}
```

### HMAC

The **HMAC** algorithm is the implementation of operations described in [§29](https://www.w3.org/TR/WebCryptoAPI/#hmac) of the W3C specification.

`import "github.com/armortal/webcrypto-go/algorithms/hmac"`.
`import "github.com/armortal/webcrypto-go/algorithms/hmac"`

#### Parameter Definitions

Expand Down
2 changes: 1 addition & 1 deletion algorithms/ecdsa/ecdsa.go
Original file line number Diff line number Diff line change
Expand Up @@ -269,7 +269,7 @@ func (s *subtleCrypto) ImportKey(format webcrypto.KeyFormat, keyData any, algori
// the implementation in this library will take these values from the algorithm provided in the params.
func importKeyPKCS8(keyData []byte, params *KeyImportParams, extractable bool, keyUsages []webcrypto.KeyUsage) (*CryptoKey, error) {
if err := util.AreUsagesValid(
[]webcrypto.KeyUsage{webcrypto.Decrypt, webcrypto.UnwrapKey}, keyUsages); err != nil {
[]webcrypto.KeyUsage{webcrypto.Sign, webcrypto.Verify}, keyUsages); err != nil {
return nil, err
}

Expand Down
6 changes: 3 additions & 3 deletions algorithms/hmac/hmac.go
Original file line number Diff line number Diff line change
Expand Up @@ -74,8 +74,8 @@ type KeyAlgorithm struct {
}

// Hash is the inner hash function to use.
func (k *KeyAlgorithm) Hash() webcrypto.KeyAlgorithm {
return nil
func (k *KeyAlgorithm) Hash() string {
return k.hash
}

// Length is the length (in bits) of the key.
Expand Down Expand Up @@ -174,7 +174,7 @@ func exportKeyAsJsonWebKey(key *CryptoKey) (*webcrypto.JsonWebKey, error) {
K: base64.RawURLEncoding.EncodeToString(key.secret),
}

switch key.algorithm.Hash().Name() {
switch key.algorithm.Hash() {
case "SHA-1":
jwk.Alg = "HS1"
case "SHA-256":
Expand Down
101 changes: 101 additions & 0 deletions examples/ecdsa/main.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
package main

import (
"fmt"

"github.com/armortal/webcrypto-go"
"github.com/armortal/webcrypto-go/algorithms/ecdsa"
)

func main() {
// generate a new P-256 ECDSA key
key, err := webcrypto.Subtle().GenerateKey(
&webcrypto.Algorithm{
Name: "ECDSA",
Params: &ecdsa.KeyGenParams{
NamedCurve: "P-256",
},
}, true, []webcrypto.KeyUsage{
webcrypto.Sign,
webcrypto.Verify,
})
if err != nil {
panic(err)
}

// key returned is a webcrypto.CryptoKeyPair
cryptoKey := key.(webcrypto.CryptoKeyPair)

// sign some data with the private key
sig, err := webcrypto.Subtle().Sign(&webcrypto.Algorithm{
Name: "ECDSA",
Params: &ecdsa.Params{
Hash: "SHA-256",
},
}, cryptoKey.PrivateKey(), []byte("test"))
if err != nil {
panic(err)
}

// verify the signature with the public key
ok, err := webcrypto.Subtle().Verify(&webcrypto.Algorithm{
Name: "ECDSA",
Params: &ecdsa.Params{
Hash: "SHA-256",
},
}, cryptoKey.PublicKey(), sig, []byte("test"))
if err != nil {
panic(err)
}

if !ok {
panic("signature didn't verify")
}

// export the public/private key as webcrypto.JsonWebKey
out, err := webcrypto.Subtle().ExportKey(webcrypto.Jwk, cryptoKey.PrivateKey())
if err != nil {
panic(err)
}

// do something with jwk
jwk := out.(*webcrypto.JsonWebKey)

// export the key as PKCS8
out, err = webcrypto.Subtle().ExportKey(webcrypto.PKCS8, cryptoKey.PrivateKey())
if err != nil {
panic(err)
}

// do something with the pkcs8 key
pkcs8 := out.([]byte)

// import a public/private key from a jwk
in, err := webcrypto.Subtle().ImportKey(webcrypto.Jwk, jwk, &webcrypto.Algorithm{
Name: "ECDSA",
Params: &ecdsa.KeyImportParams{
NamedCurve: "P-256",
},
}, true, []webcrypto.KeyUsage{
webcrypto.Sign,
})
if err != nil {
panic(err)
}

// import a public/private key from PKCS8
in, err = webcrypto.Subtle().ImportKey(webcrypto.PKCS8, pkcs8, &webcrypto.Algorithm{
Name: "ECDSA",
Params: &ecdsa.KeyImportParams{
NamedCurve: "P-256",
},
}, true, []webcrypto.KeyUsage{
webcrypto.Sign,
})
if err != nil {
panic(err)
}

// do something with the imported webcrypto.CryptoKey
fmt.Println(in.Type())
}
113 changes: 113 additions & 0 deletions examples/hmac/main.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,113 @@
package main

import (
"fmt"

"github.com/armortal/webcrypto-go"
"github.com/armortal/webcrypto-go/algorithms/hmac"
)

func main() {
// generate a new key
key, err := webcrypto.Subtle().GenerateKey(
&webcrypto.Algorithm{
Name: "HMAC",
Params: &hmac.KeyGenParams{
Hash: "SHA-256",
},
}, true, []webcrypto.KeyUsage{
webcrypto.Sign,
webcrypto.Verify,
})

if err != nil {
panic(err)
}

// the generated key returns a webcrypto.CryptoKey or
// more specifically, a *hmac.CryptoKey
cryptoKey := key.(webcrypto.CryptoKey)

// sign some data - no params required.
sig, err := webcrypto.Subtle().Sign(&webcrypto.Algorithm{
Name: "HMAC",
}, cryptoKey, []byte("test"))

if err != nil {
panic(err)
}

// verify the signature
ok, err := webcrypto.Subtle().Verify(&webcrypto.Algorithm{
Name: "HMAC",
}, cryptoKey, sig, []byte("test"))

if err != nil {
panic(err)
}

if !ok {
panic("signature didn't verify")
}

// export the key as *webcrypto.JsonWebKey
out, err := webcrypto.Subtle().ExportKey(webcrypto.Jwk, cryptoKey)
if err != nil {
panic(err)
}

jwk := out.(*webcrypto.JsonWebKey)
// do something with jwk

// export the key as raw bytes
out, err = webcrypto.Subtle().ExportKey(webcrypto.Raw, cryptoKey)
if err != nil {
panic(err)
}

raw := out.([]byte)
// do something with raw bytes

// import a key from a jwk
in, err := webcrypto.Subtle().ImportKey(
webcrypto.Jwk,
jwk,
&webcrypto.Algorithm{
Name: "HMAC",
Params: &hmac.ImportParams{
Hash: "SHA-256",
},
},
true,
[]webcrypto.KeyUsage{
webcrypto.Sign,
webcrypto.Verify,
})

if err != nil {
panic(err)
}

// import a key from raw bytes
in, err = webcrypto.Subtle().ImportKey(
webcrypto.Raw,
raw,
&webcrypto.Algorithm{
Name: "HMAC",
Params: &hmac.ImportParams{
Hash: "SHA-256",
},
},
true,
[]webcrypto.KeyUsage{
webcrypto.Sign,
webcrypto.Verify,
})

if err != nil {
panic(err)
}

// do something with your imported keys
fmt.Println(in.Type())
}

0 comments on commit 35ae19c

Please sign in to comment.