Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Derive Key #83

Draft
wants to merge 26 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from 14 commits
Commits
Show all changes
26 commits
Select commit Hold shift + click to select a range
d5d68ac
Add algorithms that didn't already exist
catdevman Jul 10, 2024
e573a20
Add ECDHKeyDeriveParams
catdevman Jul 10, 2024
977dc76
skeleton appears to be there, just need internal implementation
catdevman Jul 10, 2024
007e5bc
add derivekey operation
catdevman Jul 10, 2024
381ba93
skeleton
catdevman Jul 10, 2024
0298e06
params skeleton
catdevman Jul 10, 2024
638f53c
getting keydata
catdevman Jul 11, 2024
4eff252
deriveKey example without param
catdevman Jul 16, 2024
a24f7d8
Remove derivekey for derivebits which seems to be the operation the s…
catdevman Jul 16, 2024
2cb65bc
add DeriveKey to ecdh, hkdf, pbkdf2
catdevman Jul 16, 2024
60b701a
add examples and running them for test
catdevman Jul 16, 2024
425121f
good progress
catdevman Jul 20, 2024
1d64240
making some changes
catdevman Jul 22, 2024
4db18da
temp place to put these
catdevman Sep 26, 2024
c692850
I think this a good test... I took the example from MDN :shrug:
catdevman Oct 2, 2024
bbd2469
adding some algos that I think need to be implemented to fully do der…
catdevman Oct 2, 2024
bc62565
detect new key type and handle creating a KeyImportParam for PBKDF2
catdevman Oct 2, 2024
11d2c3c
continuing to write algo for DeriveKey
catdevman Oct 2, 2024
8a2cc56
more testing
catdevman Oct 11, 2024
e53faec
remove example for derive_key
catdevman Oct 21, 2024
58bcbd3
remove this file that had nothing in it
catdevman Oct 21, 2024
31ceaca
add pbkdf2 files; figure out why this is passing even though it shoul…
catdevman Oct 21, 2024
6023599
fix up tests so they run, failing tests are a good sign of being on t…
catdevman Oct 22, 2024
6ad2f28
add path for PBKDF2
catdevman Oct 22, 2024
1548174
privateKey and publicKey for deriveBitsPBKDF2 but I think this needs …
catdevman Oct 22, 2024
f2e26e5
clean this up later
catdevman Oct 22, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions examples/derive_key/derive-key-pbkdf2.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
import { crypto } from "k6/x/webcrypto";

export default async function () {
const key = await crypto.subtle.deriveKey();

console.log(JSON.stringify(key));
}
11 changes: 11 additions & 0 deletions webcrypto/algorithm.go
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,12 @@ const (

// ECDH represents the ECDH algorithm.
ECDH = "ECDH"

// HKDF represents the HKDF algoithm.
HKDF = "HKDF"

// PBKDF2 represents the PBKDF2 algoithm.
PBKDF2 = "PBKDF2"
)

// HashAlgorithmIdentifier represents the name of a hash algorithm.
Expand Down Expand Up @@ -115,6 +121,9 @@ const (

// OperationIdentifierDigest represents the digest operation.
OperationIdentifierDigest OperationIdentifier = "digest"

// OperationGetKeyLength represents the get key length operation.
OperationGetKeyLength OperationIdentifier = "getKeyLength"
)

// normalizeAlgorithm normalizes the given algorithm following the
Expand Down Expand Up @@ -178,6 +187,8 @@ func isRegisteredAlgorithm(algorithmName string, forOperation string) bool {
return isAesAlgorithm(algorithmName)
case OperationIdentifierSign, OperationIdentifierVerify:
return algorithmName == HMAC || algorithmName == ECDSA
case OperationIdentifierDeriveBits, OperationGetKeyLength:
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Shouldn't it be OperationIdentifierDeriveKey instead? 🙇‍♂️ (note that maybe deriveKey might rely on the bits derivation under the hood and I'm not just aware of it)

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah that is what I found the step 2 in the spec here for deriveKey requires deriveBits. So I think the issues for deriveBits need worked on first before I can continue so that is my current side mission 😄 I also realized that step 6 requires a "get key length" which was the util function I was referring to in my part 2 of the question from the other day. I think that is also going to be needed for the deriveBits issues so 2 birds 1 stone type of thing going on. Either way I am fairly sure that function will need to be our own implementation because I am not seeing it in any of the libraries that you mentioned.

return algorithmName == ECDH || algorithmName == HKDF || algorithmName == PBKDF2
default:
return false
}
Expand Down
12 changes: 12 additions & 0 deletions webcrypto/ecdh.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
package webcrypto

import "github.com/grafana/sobek"

func newECDHDeriveParams(rt *sobek.Runtime, normalized Algorithm, params sobek.Value) (*ECDHKeyDeriveParams, error) {
//TODO: add implmentation
return nil, nil
}

func (e *ECDHKeyDeriveParams) DeriveKey() (CryptoKeyGenerationResult, error){
return nil, nil
}
8 changes: 8 additions & 0 deletions webcrypto/elliptic_curve.go
Original file line number Diff line number Diff line change
Expand Up @@ -495,6 +495,14 @@ func deriveBitsECDH(privateKey CryptoKey, publicKey CryptoKey) ([]byte, error) {
return pk.ECDH(pc)
}

func deriveBitsHKDF() ([]byte, error) {
return nil, nil
}

func deriveBitsPBKDF2() ([]byte, error) {
return nil, nil
}

// The ECDSAParams represents the object that should be passed as the algorithm
// parameter into `SubtleCrypto.Sign` or `SubtleCrypto.Verify“ when using the
// ECDSA algorithm.
Expand Down
12 changes: 12 additions & 0 deletions webcrypto/hkdf.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
package webcrypto

import "github.com/grafana/sobek"

func newHKDFKeyDeriveParams(rt *sobek.Runtime, normalized Algorithm, params sobek.Value) (*HKDFParams, error) {
//TODO: add implmentation
return nil, nil
}

func (h HKDFParams) DeriveKey() (CryptoKeyGenerationResult, error){
return nil, nil
}
11 changes: 11 additions & 0 deletions webcrypto/params.go
Original file line number Diff line number Diff line change
Expand Up @@ -56,12 +56,23 @@ type HMACSignatureParams struct {
Name AlgorithmIdentifier
}

// ECDHKeyDeriveParams represents the object that should be passed as the algorithm
// parameter into `SubtleCrypto.DeriveKey`, when using the ECDHKeyDerive algorithm.
type ECDHKeyDeriveParams struct {
// Name should be set to AlgorithmKindECDH
Name AlgorithmIdentifier

// Public shoudl set the PublicKey part of a CryptoKeyPair
Public *CryptoKey
}

// PBKDF2Params represents the object that should be passed as the algorithm
// parameter into `SubtleCrypto.DeriveKey`, when using the PBKDF2 algorithm.
type PBKDF2Params struct {
// Name should be set to AlgorithmKindPbkdf2.
Name AlgorithmIdentifier

//TODO: This really needs fixed before I can call deriveKey DONE
// FIXME: should also include SHA-1, unfortunately
// Hash identifies the name of the digest algorithm to use.
// You can use any of the following:
Expand Down
26 changes: 26 additions & 0 deletions webcrypto/pbkdf2.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
package webcrypto

import "github.com/grafana/sobek"

func newPBKDF2KeyDeriveParams(rt *sobek.Runtime, normalized Algorithm, params sobek.Value) (*PBKDF2Params, error) {
//TODO: add implmentation
hashValue, err := traverseObject(rt, params, "hash")
if err != nil {
return nil, NewError(SyntaxError, "could not get hash from algorithm parameter")
}

normalizedHash, err := normalizeAlgorithm(rt, hashValue, OperationIdentifierDeriveKey)
if err != nil {

return nil, err
}
return &PBKDF2Params{
Name: normalized.Name,
Hash: normalizedHash.Name,
Salt: []byte{},
}, nil
}

func (p PBKDF2Params) DeriveKey() (CryptoKeyGenerationResult, error){
return nil, nil
}
85 changes: 79 additions & 6 deletions webcrypto/subtle_crypto.go
Original file line number Diff line number Diff line change
Expand Up @@ -564,6 +564,24 @@
return promise
}

// [x] Let algorithm, baseKey, derivedKeyType, extractable and usages be the algorithm, baseKey, derivedKeyType, extractable and keyUsages parameters passed to the deriveKey method, respectively.
// [x] Let normalizedAlgorithm be the result of normalizing an algorithm, with alg set to algorithm and op set to "deriveBits".
// [x] If an error occurred, return a Promise rejected with normalizedAlgorithm.
// [x] Let normalizedDerivedKeyAlgorithmImport be the result of normalizing an algorithm, with alg set to derivedKeyType and op set to "importKey".
// [x] If an error occurred, return a Promise rejected with normalizedDerivedKeyAlgorithmImport.
// [x] Let normalizedDerivedKeyAlgorithmLength be the result of normalizing an algorithm, with alg set to derivedKeyType and op set to "get key length".
// [x] If an error occurred, return a Promise rejected with normalizedDerivedKeyAlgorithmLength.
// [x] Let promise be a new Promise.
// [x] Return promise and asynchronously perform the remaining steps.
// [x] If the following steps or referenced procedures say to throw an error, reject promise with the returned error and then terminate the algorithm.
// [ ] If the name member of normalizedAlgorithm is not equal to the name attribute of the [[algorithm]] internal slot of baseKey then throw an InvalidAccessError.
// [ ] If the [[usages]] internal slot of baseKey does not contain an entry that is "deriveKey", then throw an InvalidAccessError.
// [ ] Let length be the result of performing the get key length algorithm specified by normalizedDerivedKeyAlgorithmLength using derivedKeyType.
// [ ] Let secret be the result of performing the derive bits operation specified by normalizedAlgorithm using key, algorithm and length.
// [ ] Let result be the result of performing the import key operation specified by normalizedDerivedKeyAlgorithmImport using "raw" as format, secret as keyData, derivedKeyType as algorithm and using extractable and usages.
// [ ] If the [[type]] internal slot of result is "secret" or "private" and usages is empty, then throw a SyntaxError.
// [ ] Resolve promise with result.

// DeriveKey can be used to derive a secret key from a master key.
//
// It takes as arguments some initial key material, the derivation
Expand All @@ -587,25 +605,80 @@
// function: for example, for PBKDF2 it might be a password, imported as a `SubtleCrypto.CryptoKey`
// using `SubtleCrypto.ImportKey`.
//
// The `derivedKeyAlgorithm` parameter should be one of:
// The `derivedKeyType` parameter should be one of:
// - an `SubtleCrypto.HMACKeyGenParams` object
// - For AES-CTR, AES-CBC, AES-GCM, AES-KW: pass an `SubtleCrypto.AESKeyGenParams`
//
// The `extractable` parameter indicates whether it will be possible to export the key
// using `SubtleCrypto.ExportKey` or `SubtleCrypto.WrapKey`.
//
// The `keyUsages` parameter is an array of strings indicating what the key can be used for.
//
//nolint:revive // remove the nolint directive when the method is implemented
func (sc *SubtleCrypto) DeriveKey(
algorithm sobek.Value,
baseKey sobek.Value,
derivedKeyAlgorithm sobek.Value,
derivedKeyType sobek.Value,
extractable bool,
keyUsages []CryptoKeyUsage,
) *sobek.Promise {
// TODO: implementation
return nil
rt := sc.vu.Runtime()
var normalizedAlgorithm, normalizedDerivedKeyAlgorithmImport, normalizedDerivedKeyAlgorithmLength Algorithm

Check failure on line 624 in webcrypto/subtle_crypto.go

View workflow job for this annotation

GitHub Actions / checks / lint

declared and not used: normalizedDerivedKeyAlgorithmImport

Check failure on line 624 in webcrypto/subtle_crypto.go

View workflow job for this annotation

GitHub Actions / checks / lint

declared and not used: normalizedDerivedKeyAlgorithmLength

Check failure on line 624 in webcrypto/subtle_crypto.go

View workflow job for this annotation

GitHub Actions / checks / lint

declared and not used: normalizedDerivedKeyAlgorithmImport

Check failure on line 624 in webcrypto/subtle_crypto.go

View workflow job for this annotation

GitHub Actions / checks / lint

declared and not used: normalizedDerivedKeyAlgorithmLength

Check failure on line 624 in webcrypto/subtle_crypto.go

View workflow job for this annotation

GitHub Actions / checks / test-build

normalizedDerivedKeyAlgorithmImport declared and not used

Check failure on line 624 in webcrypto/subtle_crypto.go

View workflow job for this annotation

GitHub Actions / checks / test-build

normalizedDerivedKeyAlgorithmLength declared and not used

Check failure on line 624 in webcrypto/subtle_crypto.go

View workflow job for this annotation

GitHub Actions / checks / test-go-versions (1.21.x, ubuntu-latest)

normalizedDerivedKeyAlgorithmImport declared and not used

Check failure on line 624 in webcrypto/subtle_crypto.go

View workflow job for this annotation

GitHub Actions / checks / test-go-versions (1.21.x, ubuntu-latest)

normalizedDerivedKeyAlgorithmLength declared and not used

Check failure on line 624 in webcrypto/subtle_crypto.go

View workflow job for this annotation

GitHub Actions / checks / test-go-versions (1.21.x, windows-latest)

normalizedDerivedKeyAlgorithmImport declared and not used

Check failure on line 624 in webcrypto/subtle_crypto.go

View workflow job for this annotation

GitHub Actions / checks / test-go-versions (1.21.x, windows-latest)

normalizedDerivedKeyAlgorithmLength declared and not used

Check failure on line 624 in webcrypto/subtle_crypto.go

View workflow job for this annotation

GitHub Actions / checks / test-go-versions (1.22.x, ubuntu-latest)

normalizedDerivedKeyAlgorithmImport declared and not used

Check failure on line 624 in webcrypto/subtle_crypto.go

View workflow job for this annotation

GitHub Actions / checks / test-go-versions (1.22.x, ubuntu-latest)

normalizedDerivedKeyAlgorithmLength declared and not used

Check failure on line 624 in webcrypto/subtle_crypto.go

View workflow job for this annotation

GitHub Actions / checks / test-go-versions (1.22.x, windows-latest)

normalizedDerivedKeyAlgorithmImport declared and not used

Check failure on line 624 in webcrypto/subtle_crypto.go

View workflow job for this annotation

GitHub Actions / checks / test-go-versions (1.22.x, windows-latest)

normalizedDerivedKeyAlgorithmLength declared and not used
var bk CryptoKey
err := func() error {
normalizedAlgorithm, err := normalizeAlgorithm(rt, algorithm, OperationIdentifierDeriveBits)

Check failure on line 627 in webcrypto/subtle_crypto.go

View workflow job for this annotation

GitHub Actions / checks / lint

declared and not used: normalizedAlgorithm

Check failure on line 627 in webcrypto/subtle_crypto.go

View workflow job for this annotation

GitHub Actions / checks / lint

declared and not used: normalizedAlgorithm

Check failure on line 627 in webcrypto/subtle_crypto.go

View workflow job for this annotation

GitHub Actions / checks / test-build

normalizedAlgorithm declared and not used

Check failure on line 627 in webcrypto/subtle_crypto.go

View workflow job for this annotation

GitHub Actions / checks / test-go-versions (1.21.x, ubuntu-latest)

normalizedAlgorithm declared and not used

Check failure on line 627 in webcrypto/subtle_crypto.go

View workflow job for this annotation

GitHub Actions / checks / test-go-versions (1.21.x, windows-latest)

normalizedAlgorithm declared and not used

Check failure on line 627 in webcrypto/subtle_crypto.go

View workflow job for this annotation

GitHub Actions / checks / test-go-versions (1.22.x, ubuntu-latest)

normalizedAlgorithm declared and not used

Check failure on line 627 in webcrypto/subtle_crypto.go

View workflow job for this annotation

GitHub Actions / checks / test-go-versions (1.22.x, windows-latest)

normalizedAlgorithm declared and not used
if err != nil {
return err
}
normalizedDerivedKeyAlgorithmImport, err := normalizeAlgorithm(rt, derivedKeyType, OperationIdentifierImportKey)

Check failure on line 631 in webcrypto/subtle_crypto.go

View workflow job for this annotation

GitHub Actions / checks / lint

declared and not used: normalizedDerivedKeyAlgorithmImport

Check failure on line 631 in webcrypto/subtle_crypto.go

View workflow job for this annotation

GitHub Actions / checks / test-build

normalizedDerivedKeyAlgorithmImport declared and not used

Check failure on line 631 in webcrypto/subtle_crypto.go

View workflow job for this annotation

GitHub Actions / checks / test-go-versions (1.21.x, ubuntu-latest)

normalizedDerivedKeyAlgorithmImport declared and not used

Check failure on line 631 in webcrypto/subtle_crypto.go

View workflow job for this annotation

GitHub Actions / checks / test-go-versions (1.21.x, windows-latest)

normalizedDerivedKeyAlgorithmImport declared and not used

Check failure on line 631 in webcrypto/subtle_crypto.go

View workflow job for this annotation

GitHub Actions / checks / test-go-versions (1.22.x, ubuntu-latest)

normalizedDerivedKeyAlgorithmImport declared and not used

Check failure on line 631 in webcrypto/subtle_crypto.go

View workflow job for this annotation

GitHub Actions / checks / test-go-versions (1.22.x, windows-latest)

normalizedDerivedKeyAlgorithmImport declared and not used
if err != nil {
return err
}
normalizedDerivedKeyAlgorithmLength, err := normalizeAlgorithm(rt, derivedKeyType, OperationGetKeyLength)

Check failure on line 635 in webcrypto/subtle_crypto.go

View workflow job for this annotation

GitHub Actions / checks / lint

declared and not used: normalizedDerivedKeyAlgorithmLength) (typecheck)

Check failure on line 635 in webcrypto/subtle_crypto.go

View workflow job for this annotation

GitHub Actions / checks / test-build

normalizedDerivedKeyAlgorithmLength declared and not used

Check failure on line 635 in webcrypto/subtle_crypto.go

View workflow job for this annotation

GitHub Actions / checks / test-go-versions (1.21.x, ubuntu-latest)

normalizedDerivedKeyAlgorithmLength declared and not used

Check failure on line 635 in webcrypto/subtle_crypto.go

View workflow job for this annotation

GitHub Actions / checks / test-go-versions (1.21.x, windows-latest)

normalizedDerivedKeyAlgorithmLength declared and not used

Check failure on line 635 in webcrypto/subtle_crypto.go

View workflow job for this annotation

GitHub Actions / checks / test-go-versions (1.22.x, ubuntu-latest)

normalizedDerivedKeyAlgorithmLength declared and not used

Check failure on line 635 in webcrypto/subtle_crypto.go

View workflow job for this annotation

GitHub Actions / checks / test-go-versions (1.22.x, windows-latest)

normalizedDerivedKeyAlgorithmLength declared and not used
if err != nil {
return err
}
return nil
}()

promise, resolve, reject := rt.NewPromise()
if err != nil {
reject(err)
return promise
}

callback := sc.vu.RegisterCallback()
go func() {
result, err := func() (CryptoKeyGenerationResult, error) {
if err = rt.ExportTo(baseKey, &bk); err != nil {
return nil, NewError(TypeError, "baseKey is not good")
}
baseKeyAlgorithmNameValue, err := traverseObject(rt, baseKey.ToObject(rt), "algorithm", "name")
if err != nil {
return nil, err
}

if normalizedAlgorithm.Name != baseKeyAlgorithmNameValue.String() {
return nil, NewError(InvalidAccessError, "Key algorithm mismatch")
}

if !bk.ContainsUsage(DeriveKeyCryptoKeyUsage) {
return nil, NewError(InvalidAccessError, "baseKey does not have deriveKey usage")
}

return nil, nil
}()

callback(func() error {
if err != nil {
reject(err)
return nil //nolint:nilerr // we return nil to indicate that the error was handled
}

resolve(result)
return nil
})
}()

return promise
}

// DeriveBits derives an array of bits from a base key.
Expand Down
1 change: 1 addition & 0 deletions webcrypto/tests/cmd_run_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,7 @@ func TestExamplesInputOutput(t *testing.T) {
"../../examples/randomUUID.js",
"../../examples/generateKey",
"../../examples/derive_bits",
"../../examples/derive_key",
"../../examples/encrypt_decrypt",
"../../examples/sign_verify",
"../../examples/import_export",
Expand Down
Empty file.
Loading