package signer import ( "crypto" "crypto/ecdsa" "crypto/rand" "crypto/rsa" "encoding/base64" "encoding/binary" "encrypter" "hash" "time" msgpack "gopkg.in/vmihailenco/msgpack.v2" ) // PrivateKey type type PrivateKey ecdsa.PrivateKey // PublicKey type type PublicKey ecdsa.PublicKey // Signature type type Signature []byte const sha256 = crypto.SHA256 const ivSize = 8 // Signer struct type Signer struct { hasher hash.Hash } // New func func New() *Signer { return &Signer{hasher: sha256.New()} } // Write func func (s *Signer) Write(data []byte) { s.hasher.Write(data) } // WriteTime func func (s *Signer) WriteTime(data *time.Time) { b := make([]byte, 8) binary.BigEndian.PutUint64(b, uint64(data.Unix())) s.hasher.Write(b) } // WritePack func func (s *Signer) WritePack(data interface{}) { raw, err := msgpack.Marshal(data) if err != nil { panic(err) } s.hasher.Write(raw) } // Reset func func (s *Signer) Reset() { s.hasher.Reset() } // Sign func func (s *Signer) Sign(key *encrypter.PrivateKey) Signature { sign, err := rsa.SignPKCS1v15(rand.Reader, (*rsa.PrivateKey)(key), sha256, s.hasher.Sum(nil)) if err != nil { panic(err) } s.hasher.Reset() return (Signature)(sign) } // Verify func func (s *Signer) Verify(key *encrypter.PublicKey, signature Signature) error { err := rsa.VerifyPKCS1v15((*rsa.PublicKey)(key), sha256, s.hasher.Sum(nil), signature) s.hasher.Reset() return err } // SignWithIV func func (s *Signer) SignWithIV(key *encrypter.PrivateKey) (Signature, error) { iv := make([]byte, ivSize) _, err := rand.Read(iv) if err != nil { return nil, err } s.hasher.Write(iv) sign, err := rsa.SignPKCS1v15(rand.Reader, (*rsa.PrivateKey)(key), sha256, s.hasher.Sum(nil)) s.hasher.Reset() return (Signature)(append(iv, sign...)), err } // VerifyWithIV func func (s *Signer) VerifyWithIV(key *encrypter.PublicKey, signature Signature) error { iv := signature[:ivSize] s.hasher.Write(iv) err := rsa.VerifyPKCS1v15((*rsa.PublicKey)(key), sha256, s.hasher.Sum(nil), signature[ivSize:]) s.hasher.Reset() return err } // MarshalJSON func func (s *Signature) MarshalJSON() ([]byte, error) { return []byte("\"" + base64.RawURLEncoding.EncodeToString(([]byte)(*s)) + "\""), nil }