github.com/aacfactory/fns@v1.2.86-0.20240310083819-80d667fc0a17/commons/signatures/ecdsa.go (about) 1 /* 2 * Copyright 2023 Wang Min Xiang 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 * 16 */ 17 18 package signatures 19 20 import ( 21 "crypto/ecdsa" 22 "crypto/rand" 23 "crypto/x509" 24 "encoding/pem" 25 "github.com/aacfactory/errors" 26 "hash" 27 "sync" 28 ) 29 30 func ECDSA(keyPEM []byte, hf HashFunc) (Signature, error) { 31 block, _ := pem.Decode(keyPEM) 32 privateKey, priErr := x509.ParsePKCS8PrivateKey(block.Bytes) 33 if priErr != nil { 34 return nil, errors.Warning("fns: create ecdsa signer failed").WithCause(errors.Warning("parse private key failed")).WithCause(priErr) 35 } 36 key, ok := privateKey.(*ecdsa.PrivateKey) 37 if !ok { 38 return nil, errors.Warning("fns: create ecdsa signer failed").WithCause(errors.Warning("private is not ecdsa")) 39 } 40 return &ecdsaSigner{ 41 pub: &key.PublicKey, 42 pri: key, 43 pool: sync.Pool{ 44 New: func() any { 45 return hf() 46 }, 47 }, 48 }, nil 49 } 50 51 type ecdsaSigner struct { 52 pub *ecdsa.PublicKey 53 pri *ecdsa.PrivateKey 54 pool sync.Pool 55 } 56 57 func (s *ecdsaSigner) acquire() (h hash.Hash) { 58 v := s.pool.Get() 59 if v != nil { 60 h = v.(hash.Hash) 61 return 62 } 63 return 64 } 65 66 func (s *ecdsaSigner) release(h hash.Hash) { 67 h.Reset() 68 s.pool.Put(h) 69 return 70 } 71 72 func (s *ecdsaSigner) Sign(target []byte) (signature []byte) { 73 h := s.acquire() 74 h.Write(target) 75 hashed := h.Sum(nil) 76 signature, _ = ecdsa.SignASN1(rand.Reader, s.pri, hashed) 77 s.release(h) 78 return 79 } 80 81 func (s *ecdsaSigner) Verify(target []byte, signature []byte) (ok bool) { 82 h := s.acquire() 83 h.Write(target) 84 hashed := h.Sum(nil) 85 ok = ecdsa.VerifyASN1(s.pub, hashed, signature) 86 s.release(h) 87 return 88 }