Skip to content

Commit b436eb7

Browse files
committed
refactor(#29): readme updates, key usages param changes
1 parent 3934d4b commit b436eb7

File tree

9 files changed

+179
-110
lines changed

9 files changed

+179
-110
lines changed

README.md

+117-48
Original file line numberDiff line numberDiff line change
@@ -50,24 +50,27 @@ This library is still in active development and all algorithms are not yet suppo
5050

5151
## Algorithms
5252

53-
When passing algorithms params into subtle functions, we use the `webcrypto.Algorithm` struct. It has the following properties:
53+
When passing algorithm params into subtle functions, we use the `webcrypto.Algorithm` struct. It has the following properties:
5454

5555
| Field | Type | Description |
5656
| :---- | :--- | :---------- |
5757
| Name | `string` | The algorithm name. |
5858
| Params | `any` | The algorithm parameters as defined by the parameters described by that algorithm in the WebCrypto specification. |
5959

60-
For each algorithm and function described below, listed are the appropriate algorithm params that need to be passed in.
60+
See specific algorithms for the parameter types to be passed in.
6161

6262
### ECDSA
6363

64-
The **ECDSA** algorithm is the implementation of operations described in [§23](https://www.w3.org/TR/WebCryptoAPI/#ecdsa) of the W3C specification.
64+
The **ECDSA** algorithm is the implementation of operations described in [§23](https://www.w3.org/TR/WebCryptoAPI/#ecdsa) of the W3C specification. You can import it into your program with `import "github.com/armortal/webcrypto-go/algorithms/ecdsa"`.
6565

6666
#### Parameter Definitions
6767

68+
Below are the parameters that supported ECDSA operations will take according to
69+
[§23.2](https://www.w3.org/TR/WebCryptoAPI/#ecdsa-registration).
70+
6871
##### Params
6972

70-
As specified in [§23.1](https://www.w3.org/TR/WebCryptoAPI/#EcdsaParams-dictionary)
73+
As specified in [§23.3](https://www.w3.org/TR/WebCryptoAPI/#EcdsaParams-dictionary)
7174

7275
| Field | Type | Description |
7376
| :---- | :--- | :---------- |
@@ -102,15 +105,15 @@ import (
102105
func main() {
103106
// generate a new P-256 ECDSA key
104107
key, err := webcrypto.Subtle().GenerateKey(
105-
&webcrypto.Algorithm{
106-
Name: "ECDSA",
107-
Params: &ecdsa.KeyGenParams{
108-
NamedCurve: "P-256",
109-
},
110-
}, true, []webcrypto.KeyUsage{
111-
webcrypto.Sign,
112-
webcrypto.Verify,
113-
})
108+
&webcrypto.Algorithm{
109+
Name: "ECDSA",
110+
Params: &ecdsa.KeyGenParams{
111+
NamedCurve: "P-256",
112+
},
113+
}, true, []webcrypto.KeyUsage{
114+
webcrypto.Sign,
115+
webcrypto.Verify,
116+
})
114117
if err != nil {
115118
panic(err)
116119
}
@@ -134,7 +137,7 @@ func main() {
134137
Name: "ECDSA",
135138
Params: &ecdsa.Params{
136139
Hash: "SHA-256",
137-
}
140+
},
138141
}, ckp.PublicKey(), sig, []byte("test"))
139142
if err != nil {
140143
panic(err)
@@ -145,7 +148,7 @@ func main() {
145148
}
146149

147150
// export the public/private key as webcrypto.JsonWebKey
148-
out, err := webcrypto.Subtle().ExportKey(webcrypto.JWK, ckp.PrivateKey())
151+
out, err := webcrypto.Subtle().ExportKey(webcrypto.Jwk, ckp.PrivateKey())
149152
if err != nil {
150153
panic(err)
151154
}
@@ -154,26 +157,51 @@ func main() {
154157

155158
// do something with jwk
156159

157-
// import a public/private key and return webcrypto.CryptoKey
158-
ck, err := webcrypto.Subtle().ImportKey(webcrypto.JWK, jwk, &webcrypto.Algorithm{
160+
// import a public/private key
161+
ck, err := webcrypto.Subtle().ImportKey(webcrypto.Jwk, jwk, &webcrypto.Algorithm{
159162
Name: "ECDSA",
160163
Params: &ecdsa.KeyImportParams{
161164
NamedCurve: "P-256",
162165
},
163-
}, true, []webcrypto.KeyUsages{
166+
}, true, []webcrypto.KeyUsage{
164167
webcrypto.Sign,
165168
})
166169
if err != nil {
167170
panic(err)
168171
}
169172

170-
// do something with the imported key
173+
// do something with the imported webcrypto.CryptoKey
171174
}
172175
```
173176

174177
### HMAC
175178

176-
The **HMAC** algorithm is the implementation of operations described in [§29](https://www.w3.org/TR/WebCryptoAPI/#hmac) of the W3C specification.
179+
The **HMAC** algorithm is the implementation of operations described in [§29](https://www.w3.org/TR/WebCryptoAPI/#hmac) of the W3C specification. You can import it into your program with `import "github.com/armortal/webcrypto-go/algorithms/hmac"`.
180+
181+
#### Parameter Definitions
182+
183+
Below are the parameters that supported HMAC operations will take according to
184+
[§29.2](https://www.w3.org/TR/WebCryptoAPI/#hmac-registration).
185+
186+
##### KeyGenParams
187+
188+
As specified in [§29.5](https://www.w3.org/TR/WebCryptoAPI/#hmac-keygen-params)
189+
190+
| Field | Type | Description |
191+
| :---- | :--- | :---------- |
192+
| Hash | `string` | The inner hash function to use. See the supported [hash algorithms](#hash-algorithms). |
193+
| Length | `uint64` | The length (in bits) of the key to generate. If unspecified, the recommended length will be used, which is the size of the associated hash function's block size. |
194+
195+
###### ImportParams
196+
197+
As specified in [§29.3](https://www.w3.org/TR/WebCryptoAPI/#hmac-importparams)
198+
199+
| Field | Type | Description |
200+
| :---- | :--- | :---------- |
201+
| Hash | `string` | The inner hash function to use. See the supported [hash algorithms](#hash-algorithms). |
202+
| Length | `uint64` | The length (in bits) of the key. |
203+
204+
#### Examples
177205

178206
```go
179207
package main
@@ -184,61 +212,102 @@ import (
184212
)
185213

186214
func main() {
187-
// Generate a new key. A *hmac.CryptoKey is returned which implements webcrypto.CryptoKey
215+
// generate a new key
188216
key, err := webcrypto.Subtle().GenerateKey(
189-
&Algorithm{
190-
Name: "ECDSA",
191-
Params: ecdsa.KeyGenParams{
192-
193-
}
194-
}
195-
&hmac.Algorithm{
196-
KeyGenParams: &hmac.KeyGenParams{
217+
&webcrypto.Algorithm{
218+
Name: "HMAC",
219+
Params: &hmac.KeyGenParams{
197220
Hash: "SHA-256",
198221
},
199-
}, true, webcrypto.Sign, webcrypto.Verify)
222+
}, true, []webcrypto.KeyUsage{
223+
webcrypto.Sign,
224+
webcrypto.Verify,
225+
})
200226

227+
if err != nil {
228+
panic(err)
229+
}
230+
231+
// the generated key returns a webcrypto.CryptoKey
201232
cryptokey := key.(webcrypto.CryptoKey)
202233

203-
// Sign some data. Note that this library uses io.Reader to pass bytes of data.
204-
sig, err := webcrypto.Subtle().Sign(
205-
&hmac.Algorithm{}, cryptokey, bytes.NewReader([]byte("helloworld")))
234+
// sign some data - no params required.
235+
sig, err := webcrypto.Subtle().Sign(&webcrypto.Algorithm{
236+
Name: "HMAC",
237+
}, cryptokey, []byte("test"))
206238

207-
// Verify the signature
208-
ok, err := webcrypto.Subtle().Verify(
209-
&hmac.Algorithm{}, cryptokey, sig, bytes.NewReader([]byte("helloworld")))
239+
if err != nil {
240+
panic(err)
241+
}
210242

211-
// Export the key as *webcrypto.JsonWebKey
243+
// verify the signature
244+
ok, err := webcrypto.Subtle().Verify(&webcrypto.Algorithm{
245+
Name: "HMAC",
246+
}, cryptokey, sig, []byte("test"))
247+
248+
if err != nil {
249+
panic(err)
250+
}
251+
252+
// export the key as *webcrypto.JsonWebKey
212253
out, err := webcrypto.Subtle().ExportKey(webcrypto.Jwk, cryptoKey)
254+
if err != nil {
255+
panic(err)
256+
}
257+
213258
jwk := out.(*webcrypto.JsonWebKey)
259+
// do something with jwk
260+
261+
// export the key as raw bytes
262+
out, err = webcrypto.Subtle().ExportKey(webcrypto.Raw, cryptoKey)
263+
if err != nil {
264+
panic(err)
265+
}
214266

215-
// Export the key as raw bytes
216-
out, err := webcrypto.Subtle().ExportKey(webcrypto.Raw, cryptoKey)
217267
raw := out.([]byte)
268+
// do something with raw bytes
218269

219-
// Import a JsonWebKey
270+
// import a key from a jwk
220271
in, err := webcrypto.Subtle().ImportKey(
221272
webcrypto.Jwk,
222273
jwk,
223-
&hmac.Algorithm{
224-
ImportParams: &hmac.ImportParams{
274+
&webcrypto.Algorithm{
275+
Name: "HMAC",
276+
Params: &hmac.ImportParams{
225277
Hash: "SHA-256",
226278
},
227279
},
228280
true,
229-
webcrypto.Sign, webcrypto.Verify)
281+
[]webcrypto.KeyUsage{
282+
webcrypto.Sign,
283+
webcrypto.Verify,
284+
})
285+
286+
if err != nil {
287+
panic(err)
288+
}
230289

231-
// Import a key from raw bytes
232-
in, err := webcrypto.Subtle().ImportKey(
290+
// import a key from raw bytes
291+
in, err = webcrypto.Subtle().ImportKey(
233292
webcrypto.Raw,
234293
raw,
235-
&hmac.Algorithm{
236-
ImportParams: &hmac.ImportParams{
294+
&webcrypto.Algorithm{
295+
Name: "HMAC",
296+
Params: &hmac.ImportParams{
237297
Hash: "SHA-256",
238298
},
239299
},
240300
true,
241-
webcrypto.Sign, webcrypto.Verify)
301+
[]webcrypto.KeyUsage{
302+
webcrypto.Sign,
303+
webcrypto.Verify,
304+
})
305+
306+
if err != nil {
307+
panic(err)
308+
}
309+
310+
// do something with your imported keys
242311
}
243312
```
244313

algorithms/ecdsa/ecdsa.go

+8-8
Original file line numberDiff line numberDiff line change
@@ -112,7 +112,7 @@ func (s *subtleCrypto) DeriveBits(algorithm *webcrypto.Algorithm, baseKey webcry
112112
}
113113

114114
// DeriveKey is not supported.
115-
func (s *subtleCrypto) DeriveKey(algorithm *webcrypto.Algorithm, baseKey webcrypto.CryptoKey, derivedKeyType *webcrypto.Algorithm, extractable bool, keyUsages ...webcrypto.KeyUsage) (webcrypto.CryptoKey, error) {
115+
func (s *subtleCrypto) DeriveKey(algorithm *webcrypto.Algorithm, baseKey webcrypto.CryptoKey, derivedKeyType *webcrypto.Algorithm, extractable bool, keyUsages []webcrypto.KeyUsage) (webcrypto.CryptoKey, error) {
116116
return nil, webcrypto.ErrMethodNotSupported()
117117
}
118118

@@ -177,7 +177,7 @@ func exportKeyJwk(key *CryptoKey) (*webcrypto.JsonWebKey, error) {
177177

178178
// GenerateKey generates a new CryptoKeyPair as per 'Generate Key' operation at
179179
// §23.7 (https://www.w3.org/TR/WebCryptoAPI/#ecdsa-operations).
180-
func (s *subtleCrypto) GenerateKey(algorithm *webcrypto.Algorithm, extractable bool, keyUsages ...webcrypto.KeyUsage) (any, error) {
180+
func (s *subtleCrypto) GenerateKey(algorithm *webcrypto.Algorithm, extractable bool, keyUsages []webcrypto.KeyUsage) (any, error) {
181181
nameAndParamsOrPanic[*KeyGenParams](algorithm)
182182
params := algorithm.Params.(*KeyGenParams)
183183

@@ -239,7 +239,7 @@ func (s *subtleCrypto) GenerateKey(algorithm *webcrypto.Algorithm, extractable b
239239
}
240240

241241
// ImportKey is not supported.
242-
func (s *subtleCrypto) ImportKey(format webcrypto.KeyFormat, keyData any, algorithm *webcrypto.Algorithm, extractable bool, keyUsages ...webcrypto.KeyUsage) (webcrypto.CryptoKey, error) {
242+
func (s *subtleCrypto) ImportKey(format webcrypto.KeyFormat, keyData any, algorithm *webcrypto.Algorithm, extractable bool, keyUsages []webcrypto.KeyUsage) (webcrypto.CryptoKey, error) {
243243
nameAndParamsOrPanic[*KeyImportParams](algorithm)
244244
params := algorithm.Params.(*KeyImportParams)
245245

@@ -249,13 +249,13 @@ func (s *subtleCrypto) ImportKey(format webcrypto.KeyFormat, keyData any, algori
249249
if !ok {
250250
return nil, webcrypto.NewError(webcrypto.ErrDataError, "keyData must be *webcrypto.JsonWebKey")
251251
}
252-
return importKeyJwk(jwk, params, extractable, keyUsages...)
252+
return importKeyJwk(jwk, params, extractable, keyUsages)
253253
case webcrypto.PKCS8:
254254
b, ok := keyData.([]byte)
255255
if !ok {
256256
return nil, webcrypto.NewError(webcrypto.ErrDataError, "keyData must be []byte")
257257
}
258-
return importKeyPKCS8(b, params, extractable, keyUsages...)
258+
return importKeyPKCS8(b, params, extractable, keyUsages)
259259
default:
260260
return nil, webcrypto.NewError(webcrypto.ErrNotSupportedError, "key format not supported")
261261
}
@@ -267,7 +267,7 @@ func (s *subtleCrypto) ImportKey(format webcrypto.KeyFormat, keyData any, algori
267267
// Although the specification states that we should first analyse the private key info as we construct our
268268
// crypto key, the standard go library doesn't support access to the underlying pkcs8 struct so
269269
// the implementation in this library will take these values from the algorithm provided in the params.
270-
func importKeyPKCS8(keyData []byte, params *KeyImportParams, extractable bool, keyUsages ...webcrypto.KeyUsage) (*CryptoKey, error) {
270+
func importKeyPKCS8(keyData []byte, params *KeyImportParams, extractable bool, keyUsages []webcrypto.KeyUsage) (*CryptoKey, error) {
271271
if err := util.AreUsagesValid(
272272
[]webcrypto.KeyUsage{webcrypto.Decrypt, webcrypto.UnwrapKey}, keyUsages); err != nil {
273273
return nil, err
@@ -313,7 +313,7 @@ func importKeyPKCS8(keyData []byte, params *KeyImportParams, extractable bool, k
313313

314314
// importKeyJwk will import a JWK. The method of importing JWK is specified at
315315
// §22.4 importKey (https://www.w3.org/TR/WebCryptoAPI/#rsa-oaep-operations).
316-
func importKeyJwk(keyData *webcrypto.JsonWebKey, params *KeyImportParams, extractable bool, keyUsages ...webcrypto.KeyUsage) (*CryptoKey, error) {
316+
func importKeyJwk(keyData *webcrypto.JsonWebKey, params *KeyImportParams, extractable bool, keyUsages []webcrypto.KeyUsage) (*CryptoKey, error) {
317317
// If the "kty" field of jwk is not a case-sensitive string match
318318
// to "EC", then throw a DataError.
319319
if keyData.Kty != "EC" {
@@ -452,7 +452,7 @@ func (s *subtleCrypto) UnwrapKey(format webcrypto.KeyFormat,
452452
unwrapAlgorithm *webcrypto.Algorithm,
453453
unwrappedKeyAlgorithm *webcrypto.Algorithm,
454454
extractable bool,
455-
keyUsages ...webcrypto.KeyUsage) (webcrypto.CryptoKey, error) {
455+
keyUsages []webcrypto.KeyUsage) (webcrypto.CryptoKey, error) {
456456
return nil, webcrypto.ErrMethodNotSupported()
457457
}
458458

algorithms/ecdsa/ecdsa_test.go

+5-5
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,7 @@ func Test_GenerateKey(t *testing.T) {
6666
Params: &KeyGenParams{
6767
NamedCurve: curve,
6868
},
69-
}, extractable, usages...)
69+
}, extractable, usages)
7070
if err != nil {
7171
t.Error(err)
7272
}
@@ -128,7 +128,7 @@ func Test_SignAndVerify(t *testing.T) {
128128
Params: &KeyGenParams{
129129
NamedCurve: P256,
130130
},
131-
}, false, webcrypto.Sign)
131+
}, false, []webcrypto.KeyUsage{webcrypto.Sign})
132132
if err != nil {
133133
t.Error(err)
134134
}
@@ -210,7 +210,7 @@ func Test_testData(t *testing.T) {
210210
t.Error(err)
211211
}
212212

213-
k, err := subtle.ImportKey(webcrypto.Jwk, &jwk, &webcrypto.Algorithm{Name: "ECDSA", Params: &KeyImportParams{NamedCurve: P256}}, true, webcrypto.Verify)
213+
k, err := subtle.ImportKey(webcrypto.Jwk, &jwk, &webcrypto.Algorithm{Name: "ECDSA", Params: &KeyImportParams{NamedCurve: P256}}, true, []webcrypto.KeyUsage{webcrypto.Verify})
214214
if err != nil {
215215
t.Error(err)
216216
}
@@ -240,7 +240,7 @@ func Test_ExportAndImportJsonWebKey(t *testing.T) {
240240
Params: &KeyGenParams{
241241
NamedCurve: P256,
242242
},
243-
}, true, webcrypto.Sign)
243+
}, true, []webcrypto.KeyUsage{webcrypto.Sign})
244244
if err != nil {
245245
t.Error(err)
246246
}
@@ -304,7 +304,7 @@ func Test_ExportAndImportJsonWebKey(t *testing.T) {
304304
}
305305

306306
// import the key
307-
imp, err := subtle.ImportKey(webcrypto.Jwk, jwk, &webcrypto.Algorithm{Name: "ECDSA", Params: &KeyImportParams{NamedCurve: P256}}, true, webcrypto.Verify)
307+
imp, err := subtle.ImportKey(webcrypto.Jwk, jwk, &webcrypto.Algorithm{Name: "ECDSA", Params: &KeyImportParams{NamedCurve: P256}}, true, []webcrypto.KeyUsage{webcrypto.Verify})
308308
if err != nil {
309309
t.Error(err)
310310
}

0 commit comments

Comments
 (0)