github.com/insolar/vanilla@v0.0.0-20201023172447-248fdf805322/cryptkit/hasher.go (about) 1 // Copyright 2020 Insolar Network Ltd. 2 // All rights reserved. 3 // This material is licensed under the Insolar License version 1.0, 4 // available at https://github.com/insolar/assured-ledger/blob/master/LICENSE.md. 5 6 package cryptkit 7 8 import ( 9 "hash" 10 "io" 11 12 "github.com/insolar/vanilla/iokit" 13 "github.com/insolar/vanilla/longbits" 14 "github.com/insolar/vanilla/throw" 15 ) 16 17 var _ hash.Hash = DigestHasher{} 18 19 type DigestHasher struct { 20 BasicDigester 21 hash.Hash 22 } 23 24 func (v DigestHasher) DigestReader(r io.Reader) DigestHasher { 25 if _, err := io.Copy(v.Hash, r); err != nil { 26 panic(err) 27 } 28 return v 29 } 30 31 func (v DigestHasher) DigestOf(w io.WriterTo) DigestHasher { 32 if _, err := w.WriteTo(v.Hash); err != nil { 33 panic(err) 34 } 35 return v 36 } 37 38 func (v DigestHasher) DigestBytes(b []byte) DigestHasher { 39 if _, err := v.Hash.Write(b); err != nil { 40 panic(err) 41 } 42 return v 43 } 44 45 func (v DigestHasher) SumToDigest() Digest { 46 return DigestOfHash(v.BasicDigester, v.Hash) 47 } 48 49 func (v DigestHasher) SumToDigestBytes(b []byte) { 50 HashToBytes(v.Hash, b) 51 } 52 53 func (v DigestHasher) SumToSignature(signer DataSigner) Signature { 54 digest := v.SumToDigest() 55 return signer.SignDigest(digest) 56 } 57 58 func HashToBytes(hasher hash.Hash, b []byte) { 59 n := len(b) 60 if h := hasher.Sum(b[:0:n]); len(h) != n { 61 panic(throw.IllegalValue()) 62 } 63 } 64 65 func ByteDigestOfHash(digester BasicDigester, hasher hash.Hash) []byte { 66 n := digester.GetDigestSize() 67 h := hasher.Sum(make([]byte, 0, n)) 68 if len(h) < n { 69 panic(throw.IllegalValue()) 70 } 71 return h[:n] 72 } 73 74 func DigestOfHash(digester BasicDigester, hasher hash.Hash) Digest { 75 h := ByteDigestOfHash(digester, hasher) 76 return NewDigest(longbits.WrapBytes(h), digester.GetDigestMethod()) 77 } 78 79 func NewHashingTeeReader(hasher DigestHasher, r io.Reader) HashingTeeReader { 80 tr := HashingTeeReader{} 81 tr.BasicDigester = hasher.BasicDigester 82 tr.CopyTo = hasher.Hash 83 tr.R = r 84 return tr 85 } 86 87 type HashingTeeReader struct { 88 BasicDigester 89 iokit.TeeReader 90 } 91 92 func (v HashingTeeReader) SumToDigest() Digest { 93 return DigestOfHash(v.BasicDigester, v.CopyTo.(hash.Hash)) 94 } 95 96 func (v *HashingTeeReader) SumToDigestAndSignature(m SigningMethod) (d Digest, s Signature, err error) { 97 d = DigestOfHash(v.BasicDigester, v.CopyTo.(hash.Hash)) 98 s, err = v.ReadSignature(m) 99 return 100 } 101 102 func (v *HashingTeeReader) ReadSignatureBytes() ([]byte, error) { 103 b := make([]byte, v.GetDigestSize()) 104 n, err := io.ReadFull(&v.TeeReader, b) 105 return b[:n], err 106 } 107 108 func (v *HashingTeeReader) ReadSignature(m SigningMethod) (Signature, error) { 109 b, err := v.ReadSignatureBytes() 110 if err != nil { 111 return Signature{}, err 112 } 113 return NewSignature(longbits.WrapBytes(b), v.GetDigestMethod().SignedBy(m)), nil 114 } 115 116 func (v *HashingTeeReader) ReadAndVerifySignature(verifier DataSignatureVerifier) ([]byte, error) { 117 d := DigestOfHash(v.BasicDigester, v.CopyTo.(hash.Hash)) 118 b, err := v.ReadSignatureBytes() 119 if err != nil { 120 return nil, err 121 } 122 s := NewSignature(longbits.WrapBytes(b), verifier.GetDefaultSignatureMethod()) 123 if !verifier.IsValidDigestSignature(d, s) { 124 err = throw.RemoteBreach("packet signature mismatch") 125 } 126 return b, err 127 }