Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Added sha 384 and 512 #84

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
89 changes: 89 additions & 0 deletions sha384.go
Original file line number Diff line number Diff line change
@@ -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()
}
107 changes: 107 additions & 0 deletions sha384_test.go
Original file line number Diff line number Diff line change
@@ -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) })
}
89 changes: 89 additions & 0 deletions sha512.go
Original file line number Diff line number Diff line change
@@ -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()
}
107 changes: 107 additions & 0 deletions sha512_test.go
Original file line number Diff line number Diff line change
@@ -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) })
}