// hashCore hashes a SectionReader using the ImoHash parameters. func (imo *ImoHash) hashCore(f *io.SectionReader) [Size]byte { var result [Size]byte imo.hasher.Reset() if f.Size() < int64(imo.sampleThreshold) || imo.sampleSize < 1 { buffer := make([]byte, f.Size()) f.Read(buffer) imo.hasher.Write(buffer) } else { buffer := make([]byte, imo.sampleSize) f.Read(buffer) imo.hasher.Write(buffer) f.Seek(f.Size()/2, 0) f.Read(buffer) imo.hasher.Write(buffer) f.Seek(int64(-imo.sampleSize), 2) f.Read(buffer) imo.hasher.Write(buffer) } hash := imo.hasher.Sum(nil) binary.PutUvarint(hash, uint64(f.Size())) copy(result[:], hash) return result }
/*ParsePackHeader A header appears at the beginning and consists of the following: 4-byte signature: The signature is: {'P', 'A', 'C', 'K'} 4-byte version number (network byte order): Git currently accepts version number 2 or 3 but generates version 2 only. 4-byte number of objects contained in the pack (network byte order) Observation: we cannot have more than 4G versions ;-) and more than 4G objects in a pack. */ func ParsePackHeader(pack *io.SectionReader) (version, objectCount uint32, err error) { buf := make([]byte, 12) _, err = pack.Read(buf) if err != nil { return } if signature := string(buf[:4]); signature != packSignature { err = errors.New("pack header has wrong signature: " + signature) return } version = binary.BigEndian.Uint32(buf[4:8]) if version != 2 { err = fmt.Errorf("version unsupport: %d ", version) return } objectCount = binary.BigEndian.Uint32(buf[8:]) return }
// newDecryptionReader returns an authenticated, decryption reader func newDecryptionReader(r *io.SectionReader, f *File) (io.Reader, error) { keyLen := aesKeyLen(f.aesStrength) saltLen := keyLen / 2 // salt is half of key len if saltLen == 0 { return nil, ErrDecryption } // grab the salt and pwvv saltpwvv := make([]byte, saltLen+2) if _, err := r.Read(saltpwvv); err != nil { return nil, err } salt := saltpwvv[:saltLen] pwvv := saltpwvv[saltLen : saltLen+2] // generate keys only if we have a password if f.password == nil { return nil, ErrPassword } decKey, authKey, pwv := generateKeys(f.password(), salt, keyLen) if !checkPasswordVerification(pwv, pwvv) { return nil, ErrPassword } dataOff := int64(saltLen + 2) dataLen := int64(f.CompressedSize64 - uint64(saltLen) - 2 - 10) // // TODO(alex): Should the compressed sizes be fixed? // // Not the ideal place to do this. // f.CompressedSize64 = uint64(dataLen) // f.CompressedSize = uint32(dataLen) data := io.NewSectionReader(r, dataOff, dataLen) authOff := dataOff + dataLen authcode := io.NewSectionReader(r, authOff, 10) ar := newAuthReader(authKey, data, authcode, f.DeferAuth) dr := decryptStream(decKey, ar) if dr == nil { return nil, ErrDecryption } return dr, nil }