From c60609cd6b0c7619b5047a480da8fb5b0d96cab0 Mon Sep 17 00:00:00 2001 From: Russ Egan Date: Fri, 26 Jan 2018 10:01:17 -0600 Subject: [PATCH] Added sha 384 and 512 --- sha384.go | 89 ++++++++++++++++++++++++++++++++++++++++ sha384_test.go | 107 +++++++++++++++++++++++++++++++++++++++++++++++++ sha512.go | 89 ++++++++++++++++++++++++++++++++++++++++ sha512_test.go | 107 +++++++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 392 insertions(+) create mode 100644 sha384.go create mode 100644 sha384_test.go create mode 100644 sha512.go create mode 100644 sha512_test.go diff --git a/sha384.go b/sha384.go new file mode 100644 index 00000000..b25e52ac --- /dev/null +++ b/sha384.go @@ -0,0 +1,89 @@ +// Copyright (C) 2014 Space Monkey, 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 openssl + +// #include "shim.h" +import "C" + +import ( + "errors" + "runtime" + "unsafe" +) + +type SHA384Hash struct { + ctx *C.EVP_MD_CTX + engine *Engine +} + +func NewSHA384Hash() (*SHA384Hash, error) { return NewSHA384HashWithEngine(nil) } + +func NewSHA384HashWithEngine(e *Engine) (*SHA384Hash, error) { + hash := &SHA384Hash{engine: e} + hash.ctx = C.X_EVP_MD_CTX_new() + if hash.ctx == nil { + return nil, errors.New("openssl: sha256: unable to allocate ctx") + } + runtime.SetFinalizer(hash, func(hash *SHA384Hash) { hash.Close() }) + if err := hash.Reset(); err != nil { + return nil, err + } + return hash, nil +} + +func (s *SHA384Hash) Close() { + if s.ctx != nil { + C.X_EVP_MD_CTX_free(s.ctx) + s.ctx = nil + } +} + +func (s *SHA384Hash) Reset() error { + if 1 != C.X_EVP_DigestInit_ex(s.ctx, C.EVP_sha384(), engineRef(s.engine)) { + return errors.New("openssl: sha384: cannot init digest ctx") + } + return nil +} + +func (s *SHA384Hash) Write(p []byte) (n int, err error) { + if len(p) == 0 { + return 0, nil + } + if 1 != C.X_EVP_DigestUpdate(s.ctx, unsafe.Pointer(&p[0]), + C.size_t(len(p))) { + return 0, errors.New("openssl: sha384: cannot update digest") + } + return len(p), nil +} + +func (s *SHA384Hash) Sum() (result [48]byte, err error) { + if 1 != C.X_EVP_DigestFinal_ex(s.ctx, + (*C.uchar)(unsafe.Pointer(&result[0])), nil) { + return result, errors.New("openssl: sha384: cannot finalize ctx") + } + return result, s.Reset() +} + +func SHA384(data []byte) (result [48]byte, err error) { + hash, err := NewSHA384Hash() + if err != nil { + return result, err + } + defer hash.Close() + if _, err := hash.Write(data); err != nil { + return result, err + } + return hash.Sum() +} diff --git a/sha384_test.go b/sha384_test.go new file mode 100644 index 00000000..404a7fcf --- /dev/null +++ b/sha384_test.go @@ -0,0 +1,107 @@ +// Copyright (C) 2014 Space Monkey, 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 openssl + +import ( + "crypto/rand" + "crypto/sha512" + "io" + "testing" +) + +func TestSHA384(t *testing.T) { + for i := 0; i < 100; i++ { + buf := make([]byte, 10*1024-i) + if _, err := io.ReadFull(rand.Reader, buf); err != nil { + t.Fatal(err) + } + + expected := sha512.Sum384(buf) + got, err := SHA384(buf) + if err != nil { + t.Fatal(err) + } + + if expected != got { + t.Fatalf("exp:%x got:%x", expected, got) + } + } +} + +func TestSHA384Writer(t *testing.T) { + ohash, err := NewSHA384Hash() + if err != nil { + t.Fatal(err) + } + hash := sha512.New384() + + for i := 0; i < 100; i++ { + if err := ohash.Reset(); err != nil { + t.Fatal(err) + } + hash.Reset() + buf := make([]byte, 10*1024-i) + if _, err := io.ReadFull(rand.Reader, buf); err != nil { + t.Fatal(err) + } + + if _, err := ohash.Write(buf); err != nil { + t.Fatal(err) + } + if _, err := hash.Write(buf); err != nil { + t.Fatal(err) + } + + var got, exp [48]byte + + hash.Sum(exp[:0]) + got, err := ohash.Sum() + if err != nil { + t.Fatal(err) + } + + if got != exp { + t.Fatalf("exp:%x got:%x", exp, got) + } + } +} + +func benchmarkSHA384(b *testing.B, length int64, fn shafunc) { + buf := make([]byte, length) + if _, err := io.ReadFull(rand.Reader, buf); err != nil { + b.Fatal(err) + } + b.SetBytes(length) + b.ResetTimer() + for i := 0; i < b.N; i++ { + fn(buf) + } +} + +func BenchmarkSHA384Large_openssl(b *testing.B) { + benchmarkSHA384(b, 1024*1024, func(buf []byte) { SHA384(buf) }) +} + +func BenchmarkSHA384Large_stdlib(b *testing.B) { + benchmarkSHA384(b, 1024*1024, func(buf []byte) { sha512.Sum384(buf) }) +} + +func BenchmarkSHA384Small_openssl(b *testing.B) { + benchmarkSHA384(b, 1, func(buf []byte) { SHA384(buf) }) +} + +func BenchmarkSHA384Small_stdlib(b *testing.B) { + benchmarkSHA384(b, 1, func(buf []byte) { sha512.Sum384(buf) }) +} diff --git a/sha512.go b/sha512.go new file mode 100644 index 00000000..45a01ae2 --- /dev/null +++ b/sha512.go @@ -0,0 +1,89 @@ +// Copyright (C) 2014 Space Monkey, 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 openssl + +// #include "shim.h" +import "C" + +import ( + "errors" + "runtime" + "unsafe" +) + +type SHA512Hash struct { + ctx *C.EVP_MD_CTX + engine *Engine +} + +func NewSHA512Hash() (*SHA512Hash, error) { return NewSHA512HashWithEngine(nil) } + +func NewSHA512HashWithEngine(e *Engine) (*SHA512Hash, error) { + hash := &SHA512Hash{engine: e} + hash.ctx = C.X_EVP_MD_CTX_new() + if hash.ctx == nil { + return nil, errors.New("openssl: sha256: unable to allocate ctx") + } + runtime.SetFinalizer(hash, func(hash *SHA512Hash) { hash.Close() }) + if err := hash.Reset(); err != nil { + return nil, err + } + return hash, nil +} + +func (s *SHA512Hash) Close() { + if s.ctx != nil { + C.X_EVP_MD_CTX_free(s.ctx) + s.ctx = nil + } +} + +func (s *SHA512Hash) Reset() error { + if 1 != C.X_EVP_DigestInit_ex(s.ctx, C.EVP_sha512(), engineRef(s.engine)) { + return errors.New("openssl: sha512: cannot init digest ctx") + } + return nil +} + +func (s *SHA512Hash) Write(p []byte) (n int, err error) { + if len(p) == 0 { + return 0, nil + } + if 1 != C.X_EVP_DigestUpdate(s.ctx, unsafe.Pointer(&p[0]), + C.size_t(len(p))) { + return 0, errors.New("openssl: sha512: cannot update digest") + } + return len(p), nil +} + +func (s *SHA512Hash) Sum() (result [64]byte, err error) { + if 1 != C.X_EVP_DigestFinal_ex(s.ctx, + (*C.uchar)(unsafe.Pointer(&result[0])), nil) { + return result, errors.New("openssl: sha512: cannot finalize ctx") + } + return result, s.Reset() +} + +func SHA512(data []byte) (result [64]byte, err error) { + hash, err := NewSHA512Hash() + if err != nil { + return result, err + } + defer hash.Close() + if _, err := hash.Write(data); err != nil { + return result, err + } + return hash.Sum() +} diff --git a/sha512_test.go b/sha512_test.go new file mode 100644 index 00000000..23abe16c --- /dev/null +++ b/sha512_test.go @@ -0,0 +1,107 @@ +// Copyright (C) 2014 Space Monkey, 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 openssl + +import ( + "crypto/rand" + "crypto/sha512" + "io" + "testing" +) + +func TestSHA512(t *testing.T) { + for i := 0; i < 100; i++ { + buf := make([]byte, 10*1024-i) + if _, err := io.ReadFull(rand.Reader, buf); err != nil { + t.Fatal(err) + } + + expected := sha512.Sum512(buf) + got, err := SHA512(buf) + if err != nil { + t.Fatal(err) + } + + if expected != got { + t.Fatalf("exp:%x got:%x", expected, got) + } + } +} + +func TestSHA512Writer(t *testing.T) { + ohash, err := NewSHA512Hash() + if err != nil { + t.Fatal(err) + } + hash := sha512.New() + + for i := 0; i < 100; i++ { + if err := ohash.Reset(); err != nil { + t.Fatal(err) + } + hash.Reset() + buf := make([]byte, 10*1024-i) + if _, err := io.ReadFull(rand.Reader, buf); err != nil { + t.Fatal(err) + } + + if _, err := ohash.Write(buf); err != nil { + t.Fatal(err) + } + if _, err := hash.Write(buf); err != nil { + t.Fatal(err) + } + + var got, exp [64]byte + + hash.Sum(exp[:0]) + got, err := ohash.Sum() + if err != nil { + t.Fatal(err) + } + + if got != exp { + t.Fatalf("exp:%x got:%x", exp, got) + } + } +} + +func benchmarkSHA512(b *testing.B, length int64, fn shafunc) { + buf := make([]byte, length) + if _, err := io.ReadFull(rand.Reader, buf); err != nil { + b.Fatal(err) + } + b.SetBytes(length) + b.ResetTimer() + for i := 0; i < b.N; i++ { + fn(buf) + } +} + +func BenchmarkSHA512Large_openssl(b *testing.B) { + benchmarkSHA512(b, 1024*1024, func(buf []byte) { SHA512(buf) }) +} + +func BenchmarkSHA512Large_stdlib(b *testing.B) { + benchmarkSHA512(b, 1024*1024, func(buf []byte) { sha512.Sum512(buf) }) +} + +func BenchmarkSHA512Small_openssl(b *testing.B) { + benchmarkSHA512(b, 1, func(buf []byte) { SHA512(buf) }) +} + +func BenchmarkSHA512Small_stdlib(b *testing.B) { + benchmarkSHA512(b, 1, func(buf []byte) { sha512.Sum512(buf) }) +}