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  }