nuts-foundation/nuts-node

View on GitHub
crypto/memory.go

Summary

Maintainability
A
35 mins
Test Coverage
D
67%
/*
 * Copyright (C) 2024 Nuts community
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <https://www.gnu.org/licenses/>.
 *
 */

package crypto

import (
    "context"
    "crypto"
    "errors"
    "maps"

    "github.com/lestrrat-go/jwx/v2/jwk"
    "github.com/nuts-foundation/nuts-node/crypto/dpop"
)

var _ JWTSigner = &MemoryJWTSigner{}
var errNotSupportedForInMemoryKeyStore = errors.New("not supported on in-memory key store")

// MemoryJWTSigner is a JWTSigner implementation that performs cryptographic operations on an in-memory JWK.
// This should only be used for low-assurance use cases, e.g. session-bound user keys.
type MemoryJWTSigner struct {
    Key jwk.Key
}

func (m MemoryJWTSigner) SignJWT(_ context.Context, claims map[string]interface{}, headers map[string]interface{}, rawKey interface{}) (string, error) {
    // copy headers so we don't change the input
    headersLocal := make(map[string]interface{})
    maps.Copy(headersLocal, headers)

    keyID, ok := rawKey.(string)
    if !ok {
        return "", errors.New("key should be string (key ID)")
    }
    if keyID != m.Key.KeyID() {
        return "", ErrPrivateKeyNotFound
    }
    var signer crypto.Signer
    if err := m.Key.Raw(&signer); err != nil {
        return "", err
    }
    alg, err := signingAlg(signer.Public())
    if err != nil {
        return "", err
    }

    headersLocal["kid"] = keyID
    return signJWT(signer, alg, claims, headersLocal)
}

func (m MemoryJWTSigner) SignJWS(_ context.Context, _ []byte, _ map[string]interface{}, _ interface{}, _ bool) (string, error) {
    return "", errNotSupportedForInMemoryKeyStore
}

func (m MemoryJWTSigner) SignDPoP(ctx context.Context, token dpop.DPoP, kid string) (string, error) {
    return "", errNotSupportedForInMemoryKeyStore
}