// Copyright 2022 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.package ecdsaimport ()// This file contains a math/big implementation of ECDSA that is only used for// deprecated custom curves.func generateLegacy( elliptic.Curve, io.Reader) (*PrivateKey, error) {iffips140only.Enforced() {returnnil, errors.New("crypto/ecdsa: use of custom curves is not allowed in FIPS 140-only mode") } , := randFieldElement(, )if != nil {returnnil, } := new(PrivateKey) .PublicKey.Curve = .D = .PublicKey.X, .PublicKey.Y = .ScalarBaseMult(.Bytes())return , nil}// hashToInt converts a hash value to an integer. Per FIPS 186-4, Section 6.4,// we use the left-most bits of the hash to match the bit-length of the order of// the curve. This also performs Step 5 of SEC 1, Version 2.0, Section 4.1.3.func hashToInt( []byte, elliptic.Curve) *big.Int { := .Params().N.BitLen() := ( + 7) / 8iflen() > { = [:] } := new(big.Int).SetBytes() := len()*8 - if > 0 { .Rsh(, uint()) }return}var errZeroParam = errors.New("zero parameter")// Sign signs a hash (which should be the result of hashing a larger message)// using the private key, priv. If the hash is longer than the bit-length of the// private key's curve order, the hash will be truncated to that length. It// returns the signature as a pair of integers. Most applications should use// [SignASN1] instead of dealing directly with r, s.//// The signature is randomized. Since Go 1.26, a secure source of random bytes// is always used, and the Reader is ignored unless GODEBUG=cryptocustomrand=1// is set. This setting will be removed in a future Go release. Instead, use// [testing/cryptotest.SetGlobalRandom].func ( io.Reader, *PrivateKey, []byte) (, *big.Int, error) { , := SignASN1(, , )if != nil {returnnil, nil, } , = new(big.Int), new(big.Int)varcryptobyte.String := cryptobyte.String()if !.ReadASN1(&, asn1.SEQUENCE) || !.Empty() || !.ReadASN1Integer() || !.ReadASN1Integer() || !.Empty() {returnnil, nil, errors.New("invalid ASN.1 from SignASN1") }return , , nil}func signLegacy( *PrivateKey, io.Reader, []byte) ( []byte, error) {iffips140only.Enforced() {returnnil, errors.New("crypto/ecdsa: use of custom curves is not allowed in FIPS 140-only mode") } := .Curve// A cheap version of hedged signatures, for the deprecated path.var [32]byteif , := io.ReadFull(, [:]); != nil {returnnil, }for , := range .D.Bytes() { [%32] ^= }for , := range { [%32] ^= } = rand.NewChaCha8()// SEC 1, Version 2.0, Section 4.1.3 := .Params().Nif .Sign() == 0 {returnnil, errZeroParam }var , , , *big.Intfor {for { , = randFieldElement(, )if != nil {returnnil, } = new(big.Int).ModInverse(, ) , _ = .ScalarBaseMult(.Bytes()) .Mod(, )if .Sign() != 0 {break } } := hashToInt(, ) = new(big.Int).Mul(.D, ) .Add(, ) .Mul(, ) .Mod(, ) // N != 0if .Sign() != 0 {break } }returnencodeSignature(.Bytes(), .Bytes())}// Verify verifies the signature in r, s of hash using the public key, pub. Its// return value records whether the signature is valid. Most applications should// use VerifyASN1 instead of dealing directly with r, s.//// The inputs are not considered confidential, and may leak through timing side// channels, or if an attacker has control of part of the inputs.func ( *PublicKey, []byte, , *big.Int) bool {if .Sign() <= 0 || .Sign() <= 0 {returnfalse } , := encodeSignature(.Bytes(), .Bytes())if != nil {returnfalse }returnVerifyASN1(, , )}func verifyLegacy( *PublicKey, []byte, []byte) bool {iffips140only.Enforced() {panic("crypto/ecdsa: use of custom curves is not allowed in FIPS 140-only mode") } , , := parseSignature()if != nil {returnfalse } , := new(big.Int).SetBytes(), new(big.Int).SetBytes() := .Curve := .Params().Nif .Sign() <= 0 || .Sign() <= 0 {returnfalse }if .Cmp() >= 0 || .Cmp() >= 0 {returnfalse }// SEC 1, Version 2.0, Section 4.1.4 := hashToInt(, ) := new(big.Int).ModInverse(, ) := .Mul(, ) .Mod(, ) := .Mul(, ) .Mod(, ) , := .ScalarBaseMult(.Bytes()) , := .ScalarMult(.X, .Y, .Bytes()) , := .Add(, , , )if .Sign() == 0 && .Sign() == 0 {returnfalse } .Mod(, )return .Cmp() == 0}var one = new(big.Int).SetInt64(1)// randFieldElement returns a random element of the order of the given// curve using the procedure given in FIPS 186-4, Appendix B.5.2.func randFieldElement( elliptic.Curve, io.Reader) ( *big.Int, error) {for { := .Params().N := make([]byte, (.BitLen()+7)/8)if _, = io.ReadFull(, ); != nil {return }if := len()*8 - .BitLen(); > 0 { [0] >>= } = new(big.Int).SetBytes()if .Sign() != 0 && .Cmp() < 0 {return } }}
The pages are generated with Goldsv0.8.3-preview. (GOOS=linux GOARCH=amd64)
Golds is a Go 101 project developed by Tapir Liu.
PR and bug reports are welcome and can be submitted to the issue list.
Please follow @zigo_101 (reachable from the left QR code) to get the latest news of Golds.