github.com/ice-blockchain/go/src@v0.0.0-20240403114104-1564d284e521/crypto/ecdsa/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 ecdsa 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 or Verify 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 var pubCache bcache.Cache[PublicKey, boringPub] 30 var privCache bcache.Cache[PrivateKey, boringPriv] 31 32 func init() { 33 pubCache.Register() 34 privCache.Register() 35 } 36 37 type boringPub struct { 38 key *boring.PublicKeyECDSA 39 orig PublicKey 40 } 41 42 func boringPublicKey(pub *PublicKey) (*boring.PublicKeyECDSA, 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.NewPublicKeyECDSA(b.orig.Curve.Params().Name, bbig.Enc(b.orig.X), bbig.Enc(b.orig.Y)) 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.PrivateKeyECDSA 61 orig PrivateKey 62 } 63 64 func boringPrivateKey(priv *PrivateKey) (*boring.PrivateKeyECDSA, 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 key, err := boring.NewPrivateKeyECDSA(b.orig.Curve.Params().Name, bbig.Enc(b.orig.X), bbig.Enc(b.orig.Y), bbig.Enc(b.orig.D)) 73 if err != nil { 74 return nil, err 75 } 76 b.key = key 77 privCache.Put(priv, b) 78 return key, nil 79 } 80 81 func publicKeyEqual(k1, k2 *PublicKey) bool { 82 return k1.X != nil && 83 k1.Curve.Params() == k2.Curve.Params() && 84 k1.X.Cmp(k2.X) == 0 && 85 k1.Y.Cmp(k2.Y) == 0 86 } 87 88 func privateKeyEqual(k1, k2 *PrivateKey) bool { 89 return publicKeyEqual(&k1.PublicKey, &k2.PublicKey) && 90 k1.D.Cmp(k2.D) == 0 91 } 92 93 func copyPublicKey(k *PublicKey) PublicKey { 94 return PublicKey{ 95 Curve: k.Curve, 96 X: new(big.Int).Set(k.X), 97 Y: new(big.Int).Set(k.Y), 98 } 99 } 100 101 func copyPrivateKey(k *PrivateKey) PrivateKey { 102 return PrivateKey{ 103 PublicKey: copyPublicKey(&k.PublicKey), 104 D: new(big.Int).Set(k.D), 105 } 106 }