mirror of https://go.googlesource.com/go
107 lines
2.7 KiB
Go
107 lines
2.7 KiB
Go
// Copyright 2017 The Go Authors. All rights reserved.
|
|
// Use of this source code is governed by a BSD-style
|
|
// license that can be found in the LICENSE file.
|
|
|
|
//go:build boringcrypto
|
|
|
|
package ecdsa
|
|
|
|
import (
|
|
"crypto/internal/boring"
|
|
"crypto/internal/boring/bbig"
|
|
"crypto/internal/boring/bcache"
|
|
"math/big"
|
|
)
|
|
|
|
// Cached conversions from Go PublicKey/PrivateKey to BoringCrypto.
|
|
//
|
|
// The first operation on a PublicKey or PrivateKey makes a parallel
|
|
// BoringCrypto key and saves it in pubCache or privCache.
|
|
//
|
|
// We could just assume that once used in a Sign or Verify operation,
|
|
// a particular key is never again modified, but that has not been a
|
|
// stated assumption before. Just in case there is any existing code that
|
|
// does modify the key between operations, we save the original values
|
|
// alongside the cached BoringCrypto key and check that the real key
|
|
// still matches before using the cached key. The theory is that the real
|
|
// operations are significantly more expensive than the comparison.
|
|
|
|
var pubCache bcache.Cache[PublicKey, boringPub]
|
|
var privCache bcache.Cache[PrivateKey, boringPriv]
|
|
|
|
func init() {
|
|
pubCache.Register()
|
|
privCache.Register()
|
|
}
|
|
|
|
type boringPub struct {
|
|
key *boring.PublicKeyECDSA
|
|
orig PublicKey
|
|
}
|
|
|
|
func boringPublicKey(pub *PublicKey) (*boring.PublicKeyECDSA, error) {
|
|
b := pubCache.Get(pub)
|
|
if b != nil && publicKeyEqual(&b.orig, pub) {
|
|
return b.key, nil
|
|
}
|
|
|
|
b = new(boringPub)
|
|
b.orig = copyPublicKey(pub)
|
|
key, err := boring.NewPublicKeyECDSA(b.orig.Curve.Params().Name, bbig.Enc(b.orig.X), bbig.Enc(b.orig.Y))
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
b.key = key
|
|
pubCache.Put(pub, b)
|
|
return key, nil
|
|
}
|
|
|
|
type boringPriv struct {
|
|
key *boring.PrivateKeyECDSA
|
|
orig PrivateKey
|
|
}
|
|
|
|
func boringPrivateKey(priv *PrivateKey) (*boring.PrivateKeyECDSA, error) {
|
|
b := privCache.Get(priv)
|
|
if b != nil && privateKeyEqual(&b.orig, priv) {
|
|
return b.key, nil
|
|
}
|
|
|
|
b = new(boringPriv)
|
|
b.orig = copyPrivateKey(priv)
|
|
key, err := boring.NewPrivateKeyECDSA(b.orig.Curve.Params().Name, bbig.Enc(b.orig.X), bbig.Enc(b.orig.Y), bbig.Enc(b.orig.D))
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
b.key = key
|
|
privCache.Put(priv, b)
|
|
return key, nil
|
|
}
|
|
|
|
func publicKeyEqual(k1, k2 *PublicKey) bool {
|
|
return k1.X != nil &&
|
|
k1.Curve.Params() == k2.Curve.Params() &&
|
|
k1.X.Cmp(k2.X) == 0 &&
|
|
k1.Y.Cmp(k2.Y) == 0
|
|
}
|
|
|
|
func privateKeyEqual(k1, k2 *PrivateKey) bool {
|
|
return publicKeyEqual(&k1.PublicKey, &k2.PublicKey) &&
|
|
k1.D.Cmp(k2.D) == 0
|
|
}
|
|
|
|
func copyPublicKey(k *PublicKey) PublicKey {
|
|
return PublicKey{
|
|
Curve: k.Curve,
|
|
X: new(big.Int).Set(k.X),
|
|
Y: new(big.Int).Set(k.Y),
|
|
}
|
|
}
|
|
|
|
func copyPrivateKey(k *PrivateKey) PrivateKey {
|
|
return PrivateKey{
|
|
PublicKey: copyPublicKey(&k.PublicKey),
|
|
D: new(big.Int).Set(k.D),
|
|
}
|
|
}
|