Some checks failed
CI / Run tests and lints (push) Failing after 29s
CI / Build CLI docs (push) Has been skipped
CI / Run Playwright end-to-end tests (mysql) (push) Failing after 3s
CI / Run Playwright end-to-end tests (postgres) (push) Failing after 2s
CI / Run Playwright end-to-end tests (sqlite) (push) Failing after 3s
CodeQL / Analyze (go) (push) Failing after 4s
CodeQL / Analyze (javascript) (push) Failing after 3s
Docker Image Scanners / scanners (push) Failing after 4s
Synchronize Issue Labels / Synchronize Issue Labels (push) Has been skipped
CI / Run end-to-end tests (postgres) (push) Failing after 19s
CI / Run end-to-end tests (sqlite) (push) Failing after 2s
CI / Run Playwright end-to-end tests (cockroach) (push) Failing after 2s
CI / Draft newsletter (push) Has been skipped
CI / Generate release (push) Has been skipped
CI / Pending approval Slack notification (push) Has been skipped
CI / Send newsletter (push) Has been skipped
122 lines
3.4 KiB
Go
122 lines
3.4 KiB
Go
/*-
|
|
* Copyright 2019 Square Inc.
|
|
*
|
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
* you may not use this file except in compliance with the License.
|
|
* You may obtain a copy of the License at
|
|
*
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
|
*
|
|
* Unless required by applicable law or agreed to in writing, software
|
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
* See the License for the specific language governing permissions and
|
|
* limitations under the License.
|
|
*/
|
|
|
|
package josex
|
|
|
|
import (
|
|
"crypto"
|
|
"crypto/ecdsa"
|
|
"crypto/ed25519"
|
|
"crypto/elliptic"
|
|
"crypto/rand"
|
|
"crypto/rsa"
|
|
"errors"
|
|
"fmt"
|
|
|
|
"github.com/go-jose/go-jose/v3"
|
|
)
|
|
|
|
// NewSigningKey generates a keypair for corresponding SignatureAlgorithm.
|
|
func NewSigningKey(alg jose.SignatureAlgorithm, bits int) (crypto.PublicKey, crypto.PrivateKey, error) {
|
|
switch alg {
|
|
case jose.ES256, jose.ES384, jose.ES512, jose.EdDSA:
|
|
keylen := map[jose.SignatureAlgorithm]int{
|
|
jose.ES256: 256,
|
|
jose.ES384: 384,
|
|
jose.ES512: 521, // sic!
|
|
jose.EdDSA: 256,
|
|
}
|
|
if bits != 0 && bits != keylen[alg] {
|
|
return nil, nil, errors.New("invalid elliptic curve key size, this algorithm does not support arbitrary size")
|
|
}
|
|
case jose.RS256, jose.RS384, jose.RS512, jose.PS256, jose.PS384, jose.PS512:
|
|
if bits == 0 {
|
|
bits = 2048
|
|
}
|
|
if bits < 2048 {
|
|
return nil, nil, errors.New("invalid key size for RSA key, 2048 or more is required")
|
|
}
|
|
}
|
|
switch alg {
|
|
case jose.ES256:
|
|
key, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader)
|
|
if err != nil {
|
|
return nil, nil, err
|
|
}
|
|
return key.Public(), key, err
|
|
case jose.ES384:
|
|
key, err := ecdsa.GenerateKey(elliptic.P384(), rand.Reader)
|
|
if err != nil {
|
|
return nil, nil, err
|
|
}
|
|
return key.Public(), key, err
|
|
case jose.ES512:
|
|
key, err := ecdsa.GenerateKey(elliptic.P521(), rand.Reader)
|
|
if err != nil {
|
|
return nil, nil, err
|
|
}
|
|
return key.Public(), key, err
|
|
case jose.EdDSA:
|
|
pub, key, err := ed25519.GenerateKey(rand.Reader)
|
|
return pub, key, err
|
|
case jose.RS256, jose.RS384, jose.RS512, jose.PS256, jose.PS384, jose.PS512:
|
|
key, err := rsa.GenerateKey(rand.Reader, bits)
|
|
if err != nil {
|
|
return nil, nil, err
|
|
}
|
|
return key.Public(), key, err
|
|
default:
|
|
return nil, nil, fmt.Errorf("unknown algorithm %s for signing key", alg)
|
|
}
|
|
}
|
|
|
|
// NewEncryptionKey generates a keypair for corresponding KeyAlgorithm.
|
|
func NewEncryptionKey(alg jose.KeyAlgorithm, bits int) (crypto.PublicKey, crypto.PrivateKey, error) {
|
|
switch alg {
|
|
case jose.RSA1_5, jose.RSA_OAEP, jose.RSA_OAEP_256:
|
|
if bits == 0 {
|
|
bits = 2048
|
|
}
|
|
if bits < 2048 {
|
|
return nil, nil, errors.New("invalid key size for RSA key, 2048 or more is required")
|
|
}
|
|
key, err := rsa.GenerateKey(rand.Reader, bits)
|
|
if err != nil {
|
|
return nil, nil, err
|
|
}
|
|
return key.Public(), key, err
|
|
case jose.ECDH_ES, jose.ECDH_ES_A128KW, jose.ECDH_ES_A192KW, jose.ECDH_ES_A256KW:
|
|
var crv elliptic.Curve
|
|
switch bits {
|
|
case 0, 256:
|
|
crv = elliptic.P256()
|
|
case 384:
|
|
crv = elliptic.P384()
|
|
case 521:
|
|
crv = elliptic.P521()
|
|
default:
|
|
return nil, nil, errors.New("invalid elliptic curve key size, use one of 256, 384, or 521")
|
|
}
|
|
key, err := ecdsa.GenerateKey(crv, rand.Reader)
|
|
if err != nil {
|
|
return nil, nil, err
|
|
}
|
|
return key.Public(), key, err
|
|
default:
|
|
return nil, nil, fmt.Errorf("unknown algorithm %s for encryption key", alg)
|
|
}
|
|
}
|