xref: /aosp_15_r20/external/tink/go/jwt/jwt_rsa_ssa_pss_verify_key_manager.go (revision e7b1675dde1b92d52ec075b0a92829627f2c52a5)
1// Copyright 2022 Google LLC
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7//      http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14//
15////////////////////////////////////////////////////////////////////////////////
16
17package jwt
18
19import (
20	"crypto/rsa"
21	"errors"
22	"fmt"
23	"math/big"
24
25	"google.golang.org/protobuf/proto"
26	"github.com/google/tink/go/core/registry"
27	"github.com/google/tink/go/internal/signature"
28	"github.com/google/tink/go/keyset"
29	jrsppb "github.com/google/tink/go/proto/jwt_rsa_ssa_pss_go_proto"
30	tinkpb "github.com/google/tink/go/proto/tink_go_proto"
31)
32
33const (
34	jwtPSVerifierKeyVersion = 0
35	jwtPSVerifierTypeURL    = "type.googleapis.com/google.crypto.tink.JwtRsaSsaPssPublicKey"
36)
37
38var errJWTPSVerifierNotImplemented = errors.New("not supported on verifier key manager")
39
40// jwtPSVerifierKeyManager implements the KeyManager interface
41// for JWT Verifier using the 'PS256', 'PS384', and 'PS512' JSON Web Algorithms (JWA).
42type jwtPSVerifierKeyManager struct{}
43
44var _ registry.KeyManager = (*jwtPSVerifierKeyManager)(nil)
45
46// adding to this map will automatically add to the list of
47// "accepted" algorithms that will construct valid primitives.
48var validPSAlgToHash = map[jrsppb.JwtRsaSsaPssAlgorithm]string{
49	jrsppb.JwtRsaSsaPssAlgorithm_PS256: "SHA256",
50	jrsppb.JwtRsaSsaPssAlgorithm_PS384: "SHA384",
51	jrsppb.JwtRsaSsaPssAlgorithm_PS512: "SHA512",
52}
53
54var psAlgToSaltLen = map[jrsppb.JwtRsaSsaPssAlgorithm]int{
55	jrsppb.JwtRsaSsaPssAlgorithm_PS256: 32,
56	jrsppb.JwtRsaSsaPssAlgorithm_PS384: 48,
57	jrsppb.JwtRsaSsaPssAlgorithm_PS512: 64,
58}
59
60func (km *jwtPSVerifierKeyManager) Primitive(serializedKey []byte) (interface{}, error) {
61	if serializedKey == nil || len(serializedKey) == 0 {
62		return nil, fmt.Errorf("invalid key")
63	}
64	pubKey := &jrsppb.JwtRsaSsaPssPublicKey{}
65	if err := proto.Unmarshal(serializedKey, pubKey); err != nil {
66		return nil, err
67	}
68	if err := validatePSPublicKey(pubKey); err != nil {
69		return nil, err
70	}
71	e := new(big.Int).SetBytes(pubKey.GetE())
72	if !e.IsInt64() {
73		return nil, fmt.Errorf("public exponent can't fit in a 64 bit integer")
74	}
75	rsaPubKey := &rsa.PublicKey{
76		N: new(big.Int).SetBytes(pubKey.GetN()),
77		E: int(e.Int64()),
78	}
79	algorithm := pubKey.GetAlgorithm()
80	v, err := signature.New_RSA_SSA_PSS_Verifier(validPSAlgToHash[algorithm], psAlgToSaltLen[algorithm], rsaPubKey)
81	if err != nil {
82		return nil, err
83	}
84	return newVerifierWithKID(v, algorithm.String(), psCustomKID(pubKey))
85}
86
87func (km *jwtPSVerifierKeyManager) NewKey(serializedKeyFormat []byte) (proto.Message, error) {
88	return nil, errJWTPSVerifierNotImplemented
89}
90
91func (km *jwtPSVerifierKeyManager) NewKeyData(serializedKeyFormat []byte) (*tinkpb.KeyData, error) {
92	return nil, errJWTPSVerifierNotImplemented
93}
94
95func (km *jwtPSVerifierKeyManager) DoesSupport(typeURL string) bool {
96	return typeURL == jwtPSVerifierTypeURL
97}
98
99func (km *jwtPSVerifierKeyManager) TypeURL() string {
100	return jwtPSVerifierTypeURL
101}
102
103func validatePSPublicKey(pubKey *jrsppb.JwtRsaSsaPssPublicKey) error {
104	if pubKey == nil {
105		return fmt.Errorf("nil public key")
106	}
107	if err := keyset.ValidateKeyVersion(pubKey.Version, jwtPSVerifierKeyVersion); err != nil {
108		return err
109	}
110	if _, ok := validPSAlgToHash[pubKey.GetAlgorithm()]; !ok {
111		return fmt.Errorf("invalid algorithm")
112	}
113	e := new(big.Int).SetBytes(pubKey.GetE())
114	if !e.IsInt64() {
115		return fmt.Errorf("public exponent can't fit in a 64 bit integer")
116	}
117	if err := signature.RSAValidPublicExponent(int(e.Int64())); err != nil {
118		return err
119	}
120	return signature.RSAValidModulusSizeInBits(new(big.Int).SetBytes(pubKey.GetN()).BitLen())
121}
122
123func psCustomKID(pk *jrsppb.JwtRsaSsaPssPublicKey) *string {
124	// nil is an acceptable value for a custom kid.
125	if pk.GetCustomKid() == nil {
126		return nil
127	}
128	k := pk.GetCustomKid().GetValue()
129	return &k
130}
131