github.com/aacfactory/fns@v1.2.86-0.20240310083819-80d667fc0a17/commons/signatures/rsa.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" 22 "crypto/rand" 23 "crypto/rsa" 24 "crypto/sha256" 25 "crypto/x509" 26 "encoding/pem" 27 "github.com/aacfactory/errors" 28 "hash" 29 "sync" 30 ) 31 32 func RSA(keyPEM []byte) (Signature, error) { 33 block, _ := pem.Decode(keyPEM) 34 privateKey, priErr := x509.ParsePKCS8PrivateKey(block.Bytes) 35 if priErr != nil { 36 return nil, errors.Warning("fns: create rsa signer failed").WithCause(errors.Warning("parse private key failed")).WithCause(priErr) 37 } 38 key, ok := privateKey.(*rsa.PrivateKey) 39 if !ok { 40 return nil, errors.Warning("fns: create rsa signer failed").WithCause(errors.Warning("private is not rsa")) 41 } 42 return &rsaSigner{ 43 pub: &key.PublicKey, 44 pri: key, 45 pool: sync.Pool{ 46 New: func() any { 47 return sha256.New() 48 }, 49 }, 50 }, nil 51 } 52 53 type rsaSigner struct { 54 pub *rsa.PublicKey 55 pri *rsa.PrivateKey 56 pool sync.Pool 57 } 58 59 func (s *rsaSigner) acquire() (h hash.Hash) { 60 v := s.pool.Get() 61 if v != nil { 62 h = v.(hash.Hash) 63 return 64 } 65 h = sha256.New() 66 return 67 } 68 69 func (s *rsaSigner) release(h hash.Hash) { 70 h.Reset() 71 s.pool.Put(h) 72 return 73 } 74 75 func (s *rsaSigner) Sign(target []byte) (signature []byte) { 76 h := s.acquire() 77 h.Write(target) 78 hashed := h.Sum(nil) 79 signature, _ = rsa.SignPKCS1v15(rand.Reader, s.pri, crypto.SHA256, hashed) 80 s.release(h) 81 return 82 } 83 84 func (s *rsaSigner) Verify(target []byte, signature []byte) (ok bool) { 85 h := s.acquire() 86 h.Write(target) 87 hashed := h.Sum(nil) 88 ok = rsa.VerifyPKCS1v15(s.pub, crypto.SHA256, hashed, signature) == nil 89 s.release(h) 90 return 91 }