/*- * 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) } }