github.com/ice-blockchain/go/src@v0.0.0-20240403114104-1564d284e521/crypto/rsa/boring.go (about) 1 // Copyright 2017 The Go Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style 3 // license that can be found in the LICENSE file. 4 5 //go:build boringcrypto 6 7 package rsa 8 9 import ( 10 "crypto/internal/boring" 11 "crypto/internal/boring/bbig" 12 "crypto/internal/boring/bcache" 13 "math/big" 14 ) 15 16 // Cached conversions from Go PublicKey/PrivateKey to BoringCrypto. 17 // 18 // The first operation on a PublicKey or PrivateKey makes a parallel 19 // BoringCrypto key and saves it in pubCache or privCache. 20 // 21 // We could just assume that once used in a sign/verify/encrypt/decrypt operation, 22 // a particular key is never again modified, but that has not been a 23 // stated assumption before. Just in case there is any existing code that 24 // does modify the key between operations, we save the original values 25 // alongside the cached BoringCrypto key and check that the real key 26 // still matches before using the cached key. The theory is that the real 27 // operations are significantly more expensive than the comparison. 28 29 type boringPub struct { 30 key *boring.PublicKeyRSA 31 orig PublicKey 32 } 33 34 var pubCache bcache.Cache[PublicKey, boringPub] 35 var privCache bcache.Cache[PrivateKey, boringPriv] 36 37 func init() { 38 pubCache.Register() 39 privCache.Register() 40 } 41 42 func boringPublicKey(pub *PublicKey) (*boring.PublicKeyRSA, error) { 43 b := pubCache.Get(pub) 44 if b != nil && publicKeyEqual(&b.orig, pub) { 45 return b.key, nil 46 } 47 48 b = new(boringPub) 49 b.orig = copyPublicKey(pub) 50 key, err := boring.NewPublicKeyRSA(bbig.Enc(b.orig.N), bbig.Enc(big.NewInt(int64(b.orig.E)))) 51 if err != nil { 52 return nil, err 53 } 54 b.key = key 55 pubCache.Put(pub, b) 56 return key, nil 57 } 58 59 type boringPriv struct { 60 key *boring.PrivateKeyRSA 61 orig PrivateKey 62 } 63 64 func boringPrivateKey(priv *PrivateKey) (*boring.PrivateKeyRSA, error) { 65 b := privCache.Get(priv) 66 if b != nil && privateKeyEqual(&b.orig, priv) { 67 return b.key, nil 68 } 69 70 b = new(boringPriv) 71 b.orig = copyPrivateKey(priv) 72 73 var N, E, D, P, Q, Dp, Dq, Qinv *big.Int 74 N = b.orig.N 75 E = big.NewInt(int64(b.orig.E)) 76 D = b.orig.D 77 if len(b.orig.Primes) == 2 { 78 P = b.orig.Primes[0] 79 Q = b.orig.Primes[1] 80 Dp = b.orig.Precomputed.Dp 81 Dq = b.orig.Precomputed.Dq 82 Qinv = b.orig.Precomputed.Qinv 83 } 84 key, err := boring.NewPrivateKeyRSA(bbig.Enc(N), bbig.Enc(E), bbig.Enc(D), bbig.Enc(P), bbig.Enc(Q), bbig.Enc(Dp), bbig.Enc(Dq), bbig.Enc(Qinv)) 85 if err != nil { 86 return nil, err 87 } 88 b.key = key 89 privCache.Put(priv, b) 90 return key, nil 91 } 92 93 func publicKeyEqual(k1, k2 *PublicKey) bool { 94 return k1.N != nil && 95 k1.N.Cmp(k2.N) == 0 && 96 k1.E == k2.E 97 } 98 99 func copyPublicKey(k *PublicKey) PublicKey { 100 return PublicKey{ 101 N: new(big.Int).Set(k.N), 102 E: k.E, 103 } 104 } 105 106 func privateKeyEqual(k1, k2 *PrivateKey) bool { 107 return publicKeyEqual(&k1.PublicKey, &k2.PublicKey) && 108 k1.D.Cmp(k2.D) == 0 109 } 110 111 func copyPrivateKey(k *PrivateKey) PrivateKey { 112 dst := PrivateKey{ 113 PublicKey: copyPublicKey(&k.PublicKey), 114 D: new(big.Int).Set(k.D), 115 } 116 dst.Primes = make([]*big.Int, len(k.Primes)) 117 for i, p := range k.Primes { 118 dst.Primes[i] = new(big.Int).Set(p) 119 } 120 if x := k.Precomputed.Dp; x != nil { 121 dst.Precomputed.Dp = new(big.Int).Set(x) 122 } 123 if x := k.Precomputed.Dq; x != nil { 124 dst.Precomputed.Dq = new(big.Int).Set(x) 125 } 126 if x := k.Precomputed.Qinv; x != nil { 127 dst.Precomputed.Qinv = new(big.Int).Set(x) 128 } 129 return dst 130 }