Minor refactoring: header checksum now covers _all_ of the header
This commit is contained in:
parent
374daebb8d
commit
262a554356
2 changed files with 48 additions and 24 deletions
|
@ -10,6 +10,24 @@
|
||||||
// This software does not come with any express or implied
|
// This software does not come with any express or implied
|
||||||
// warranty; it is provided "as is". No claim is made to its
|
// warranty; it is provided "as is". No claim is made to its
|
||||||
// suitability for any purpose.
|
// suitability for any purpose.
|
||||||
|
//
|
||||||
|
// Notes
|
||||||
|
// =====
|
||||||
|
// Header: Fixed size + Variable list of recipients
|
||||||
|
// Fixed size header:
|
||||||
|
// - Magic: 7 bytes
|
||||||
|
// - Version: 1 byte
|
||||||
|
// - VLen: 4 byte
|
||||||
|
//
|
||||||
|
// Variable Length Segment:
|
||||||
|
// - Shasum: 32 bytes (SHA256 of full header)
|
||||||
|
// - Protobuf encoded recipient info
|
||||||
|
//
|
||||||
|
// The variable length segment consists of one or more
|
||||||
|
// recipients, their wrapped keys etc. This is encoded as
|
||||||
|
// a protobuf message. This protobuf encoded message immediately
|
||||||
|
// follows the fixed length header.
|
||||||
|
//
|
||||||
|
|
||||||
package sign
|
package sign
|
||||||
|
|
||||||
|
@ -37,6 +55,7 @@ const EOF uint32 = 1 << 31
|
||||||
const _Magic = "SigTool"
|
const _Magic = "SigTool"
|
||||||
const _MagicLen = len(_Magic)
|
const _MagicLen = len(_Magic)
|
||||||
const _AEADNonceLen = 32
|
const _AEADNonceLen = 32
|
||||||
|
const _FixedHdrLen = _MagicLen + 1 + 4
|
||||||
|
|
||||||
// Encryptor holds the encryption context
|
// Encryptor holds the encryption context
|
||||||
type Encryptor struct {
|
type Encryptor struct {
|
||||||
|
@ -114,36 +133,35 @@ func (e *Encryptor) AddRecipient(pk *PublicKey) error {
|
||||||
|
|
||||||
// Begin the encryption process by writing the header
|
// Begin the encryption process by writing the header
|
||||||
func (e *Encryptor) start(wr io.Writer) error {
|
func (e *Encryptor) start(wr io.Writer) error {
|
||||||
msize := e.Size()
|
varHdrLen := sha256.Size + e.Size()
|
||||||
|
|
||||||
// marshal the header and recipients
|
hdrBuf := make([]byte, _FixedHdrLen + varHdrLen)
|
||||||
hdrlen := _MagicLen + 1 + 4 + sha256.Size
|
|
||||||
|
|
||||||
buf := make([]byte, hdrlen+msize)
|
fixedHdr := hdrBuf[:_FixedHdrLen]
|
||||||
hdrbuf := buf[hdrlen:]
|
varHdr := hdrBuf[_FixedHdrLen:]
|
||||||
|
|
||||||
copy(buf[:], []byte(_Magic))
|
cksum := varHdr[:sha256.Size]
|
||||||
|
pbHdr := varHdr[sha256.Size:]
|
||||||
|
|
||||||
buf[_MagicLen] = 1 // file version#
|
// Now assemble the fixed header
|
||||||
|
copy(fixedHdr[:], []byte(_Magic))
|
||||||
// The fixed header is the magic _and _ the length of the variable segment.
|
fixedHdr[_MagicLen] = 1 // version #
|
||||||
// So, we capture the length of the variable portion first.
|
binary.BigEndian.PutUint32(fixedHdr[_MagicLen+1:], uint32(varHdrLen))
|
||||||
binary.BigEndian.PutUint32(buf[_MagicLen+1:], uint32(sha256.Size+msize))
|
|
||||||
|
|
||||||
// Now marshal the variable portion
|
// Now marshal the variable portion
|
||||||
_, err := e.MarshalToSizedBuffer(hdrbuf)
|
_, err := e.MarshalToSizedBuffer(pbHdr)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("encrypt: can't marshal header: %s", err)
|
return fmt.Errorf("encrypt: can't marshal header: %s", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
// and calculate the header checksum
|
// Now calculate checksum of everything
|
||||||
cksum := buf[_MagicLen+1+4:]
|
|
||||||
h := sha256.New()
|
h := sha256.New()
|
||||||
h.Write(hdrbuf)
|
h.Write(fixedHdr)
|
||||||
|
h.Write(pbHdr)
|
||||||
h.Sum(cksum[:0])
|
h.Sum(cksum[:0])
|
||||||
|
|
||||||
// Finally write it out
|
// Finally write it out
|
||||||
err = fullwrite(buf, wr)
|
err = fullwrite(hdrBuf, wr)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("encrypt: %s", err)
|
return fmt.Errorf("encrypt: %s", err)
|
||||||
}
|
}
|
||||||
|
@ -252,7 +270,7 @@ type Decryptor struct {
|
||||||
// Create a new decryption context and if 'pk' is given, check that it matches
|
// Create a new decryption context and if 'pk' is given, check that it matches
|
||||||
// the sender
|
// the sender
|
||||||
func NewDecryptor(rd io.Reader) (*Decryptor, error) {
|
func NewDecryptor(rd io.Reader) (*Decryptor, error) {
|
||||||
var b [12]byte
|
var b [_FixedHdrLen]byte
|
||||||
|
|
||||||
_, err := io.ReadFull(rd, b[:])
|
_, err := io.ReadFull(rd, b[:])
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -268,8 +286,10 @@ func NewDecryptor(rd io.Reader) (*Decryptor, error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
hdrlen := binary.BigEndian.Uint32(b[_MagicLen+1:])
|
hdrlen := binary.BigEndian.Uint32(b[_MagicLen+1:])
|
||||||
if hdrlen > 65536 {
|
|
||||||
return nil, fmt.Errorf("decrypt: header too large (max 65536)")
|
// sanity check on variable segment length
|
||||||
|
if hdrlen > 1048576 {
|
||||||
|
return nil, fmt.Errorf("decrypt: header too large (max 1048576)")
|
||||||
}
|
}
|
||||||
if hdrlen < 32 {
|
if hdrlen < 32 {
|
||||||
return nil, fmt.Errorf("decrypt: header too small (min 32)")
|
return nil, fmt.Errorf("decrypt: header too small (min 32)")
|
||||||
|
@ -282,10 +302,14 @@ func NewDecryptor(rd io.Reader) (*Decryptor, error) {
|
||||||
return nil, fmt.Errorf("decrypt: err while reading header: %s", err)
|
return nil, fmt.Errorf("decrypt: err while reading header: %s", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
verify := hdr[:32]
|
verify := hdr[:sha256.Size]
|
||||||
hdr = hdr[32:]
|
pbHdr := hdr[sha256.Size:]
|
||||||
|
|
||||||
|
h := sha256.New()
|
||||||
|
h.Write(b[:])
|
||||||
|
h.Write(pbHdr)
|
||||||
|
cksum := h.Sum(nil)
|
||||||
|
|
||||||
cksum := sha256.Sum256(hdr)
|
|
||||||
if subtle.ConstantTimeCompare(verify, cksum[:]) == 0 {
|
if subtle.ConstantTimeCompare(verify, cksum[:]) == 0 {
|
||||||
return nil, fmt.Errorf("decrypt: header corrupted")
|
return nil, fmt.Errorf("decrypt: header corrupted")
|
||||||
}
|
}
|
||||||
|
@ -294,7 +318,7 @@ func NewDecryptor(rd io.Reader) (*Decryptor, error) {
|
||||||
rd: rd,
|
rd: rd,
|
||||||
}
|
}
|
||||||
|
|
||||||
err = d.Header.Unmarshal(hdr)
|
err = d.Header.Unmarshal(pbHdr)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("decrypt: decode error: %s", err)
|
return nil, fmt.Errorf("decrypt: decode error: %s", err)
|
||||||
}
|
}
|
||||||
|
|
2
version
2
version
|
@ -1 +1 @@
|
||||||
0.6.1
|
0.6.2
|
||||||
|
|
Loading…
Add table
Reference in a new issue