From f1410731db23db880a556f4cb951933be8d0fb79 Mon Sep 17 00:00:00 2001 From: Harshavardhana Date: Wed, 24 Jun 2015 14:16:28 -0700 Subject: [PATCH] Add windows code for sha1 and crc32c --- pkg/utils/checksum/crc32c/crc32c_windows.go | 51 ++++++ pkg/utils/crypto/sha1/sha1_windows.go | 167 ++++++++++++++++++++ 2 files changed, 218 insertions(+) create mode 100644 pkg/utils/checksum/crc32c/crc32c_windows.go create mode 100644 pkg/utils/crypto/sha1/sha1_windows.go diff --git a/pkg/utils/checksum/crc32c/crc32c_windows.go b/pkg/utils/checksum/crc32c/crc32c_windows.go new file mode 100644 index 000000000..f657d003c --- /dev/null +++ b/pkg/utils/checksum/crc32c/crc32c_windows.go @@ -0,0 +1,51 @@ +/* + * Minimalist Object Storage, (C) 2014 Minio, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package crc32c + +import ( + "hash/crc32" + "io" +) + +var castanagoliTable = crc32.MakeTable(crc32.Castagnoli) + +/// Convenience functions + +// Sum32 - single caller crc helper +func Sum32(buffer []byte) uint32 { + crc := crc32.New(castanagoliTable) + crc.Reset() + crc.Write(buffer) + return crc.Sum32() +} + +// Sum - io.Reader based crc helper +func Sum(reader io.Reader) (uint32, error) { + h := crc32.New(castanagoliTable) + var err error + for err == nil { + length := 0 + byteBuffer := make([]byte, 1024*1024) + length, err = reader.Read(byteBuffer) + byteBuffer = byteBuffer[0:length] + h.Write(byteBuffer) + } + if err != io.EOF { + return 0, err + } + return h.Sum32(), nil +} diff --git a/pkg/utils/crypto/sha1/sha1_windows.go b/pkg/utils/crypto/sha1/sha1_windows.go new file mode 100644 index 000000000..05a9cb333 --- /dev/null +++ b/pkg/utils/crypto/sha1/sha1_windows.go @@ -0,0 +1,167 @@ +// Copyright 2009 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file of +// Golang project: +// https://github.com/golang/go/blob/master/LICENSE + +// Using this part of Minio codebase under the license +// Apache License Version 2.0 with modifications + +// Package sha1 implements the SHA1 hash algorithm as defined in RFC 3174. +package sha1 + +import ( + "hash" + "io" + + "github.com/minio/minio/pkg/utils/cpu" +) + +// The size of a SHA1 checksum in bytes. +const Size = 20 + +// The blocksize of SHA1 in bytes. +const BlockSize = 64 + +const ( + chunk = 64 + init0 = 0x67452301 + init1 = 0xEFCDAB89 + init2 = 0x98BADCFE + init3 = 0x10325476 + init4 = 0xC3D2E1F0 +) + +// digest represents the partial evaluation of a checksum. +type digest struct { + h [5]uint32 + x [chunk]byte + nx int + len uint64 +} + +// Reset digest +func (d *digest) Reset() { + d.h[0] = init0 + d.h[1] = init1 + d.h[2] = init2 + d.h[3] = init3 + d.h[4] = init4 + d.nx = 0 + d.len = 0 +} + +// New returns a new hash.Hash computing the SHA1 checksum. +func New() hash.Hash { + d := new(digest) + d.Reset() + return d +} + +func block(dig *digest, p []byte) { + switch true { + case cpu.HasSSE41() == true: + blockSSE3(dig, p) + default: + blockGeneric(dig, p) + } +} + +// Return output size +func (d *digest) Size() int { return Size } + +// Return checksum blocksize +func (d *digest) BlockSize() int { return BlockSize } + +// Write to digest +func (d *digest) Write(p []byte) (nn int, err error) { + nn = len(p) + d.len += uint64(nn) + if d.nx > 0 { + n := copy(d.x[d.nx:], p) + d.nx += n + if d.nx == chunk { + block(d, d.x[:]) + d.nx = 0 + } + p = p[n:] + } + if len(p) >= chunk { + n := len(p) &^ (chunk - 1) + block(d, p[:n]) + p = p[n:] + } + if len(p) > 0 { + d.nx = copy(d.x[:], p) + } + return +} + +// Return checksum bytes +func (d *digest) Sum(in []byte) []byte { + // Make a copy of d0 so that caller can keep writing and summing. + d0 := *d + hash := d0.checkSum() + return append(in, hash[:]...) +} + +// Intermediate checksum function +func (d *digest) checkSum() [Size]byte { + len := d.len + // Padding. Add a 1 bit and 0 bits until 56 bytes mod 64. + var tmp [64]byte + tmp[0] = 0x80 + if len%64 < 56 { + d.Write(tmp[0 : 56-len%64]) + } else { + d.Write(tmp[0 : 64+56-len%64]) + } + + // Length in bits. + len <<= 3 + for i := uint(0); i < 8; i++ { + tmp[i] = byte(len >> (56 - 8*i)) + } + d.Write(tmp[0:8]) + + if d.nx != 0 { + panic("d.nx != 0") + } + + var digest [Size]byte + for i, s := range d.h { + digest[i*4] = byte(s >> 24) + digest[i*4+1] = byte(s >> 16) + digest[i*4+2] = byte(s >> 8) + digest[i*4+3] = byte(s) + } + + return digest +} + +/// Convenience functions + +// Sum1 - single caller sha1 helper +func Sum1(data []byte) [Size]byte { + var d digest + d.Reset() + d.Write(data) + return d.checkSum() +} + +// Sum - io.Reader based streaming sha1 helper +func Sum(reader io.Reader) ([]byte, error) { + h := New() + var err error + for err == nil { + length := 0 + byteBuffer := make([]byte, 1024*1024) + length, err = reader.Read(byteBuffer) + byteBuffer = byteBuffer[0:length] + h.Write(byteBuffer) + } + if err != io.EOF { + return nil, err + } + return h.Sum(nil), nil +}