Skip to content
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.

Commit c1c0ec6

Browse files
author
Vitaly Isaev
committedAug 8, 2019
Support all available hash functions to compute message digests
1 parent c2dcc5c commit c1c0ec6

13 files changed

+589
-216
lines changed
 

‎.gitignore

+1
Original file line numberDiff line numberDiff line change
@@ -1 +1,2 @@
11
openssl.test
2+
.idea

‎cert.go

-18
Original file line numberDiff line numberDiff line change
@@ -26,24 +26,6 @@ import (
2626
"unsafe"
2727
)
2828

29-
type EVP_MD int
30-
31-
const (
32-
EVP_NULL EVP_MD = iota
33-
EVP_MD5 EVP_MD = iota
34-
EVP_MD4 EVP_MD = iota
35-
EVP_SHA EVP_MD = iota
36-
EVP_SHA1 EVP_MD = iota
37-
EVP_DSS EVP_MD = iota
38-
EVP_DSS1 EVP_MD = iota
39-
EVP_MDC2 EVP_MD = iota
40-
EVP_RIPEMD160 EVP_MD = iota
41-
EVP_SHA224 EVP_MD = iota
42-
EVP_SHA256 EVP_MD = iota
43-
EVP_SHA384 EVP_MD = iota
44-
EVP_SHA512 EVP_MD = iota
45-
)
46-
4729
// X509_Version represents a version on an x509 certificate.
4830
type X509_Version int
4931

‎ctx.go

+1-2
Original file line numberDiff line numberDiff line change
@@ -298,8 +298,7 @@ func (s *CertificateStore) AddCertificate(cert *Certificate) error {
298298
}
299299

300300
type CertificateStoreCtx struct {
301-
ctx *C.X509_STORE_CTX
302-
ssl_ctx *Ctx
301+
ctx *C.X509_STORE_CTX
303302
}
304303

305304
func (self *CertificateStoreCtx) VerifyResult() VerifyResult {

‎digest_computer.go

+68
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
package openssl
2+
3+
// #include "shim.h"
4+
import "C"
5+
import (
6+
"fmt"
7+
"runtime"
8+
"unsafe"
9+
)
10+
11+
// DigestComputer is a generic structure to compute message digest
12+
// with any hash function supported by OpenSSL
13+
type DigestComputer struct {
14+
ctx *C.EVP_MD_CTX
15+
engine *Engine
16+
evpMD EVP_MD
17+
}
18+
19+
func NewDigestComputer(digestType EVP_MD) (*DigestComputer, error) {
20+
return NewDigestComputerWithEngine(nil, digestType)
21+
}
22+
23+
func NewDigestComputerWithEngine(e *Engine, digestType EVP_MD) (*DigestComputer, error) {
24+
hash := &DigestComputer{engine: e, evpMD: digestType}
25+
hash.ctx = C.X_EVP_MD_CTX_new()
26+
if hash.ctx == nil {
27+
return nil, fmt.Errorf("openssl: %s: unable to allocate ctx", digestType.String())
28+
}
29+
runtime.SetFinalizer(hash, func(hash *DigestComputer) { hash.Close() })
30+
if err := hash.Reset(); err != nil {
31+
return nil, err
32+
}
33+
return hash, nil
34+
}
35+
36+
func (s *DigestComputer) Close() {
37+
if s.ctx != nil {
38+
C.X_EVP_MD_CTX_free(s.ctx)
39+
s.ctx = nil
40+
}
41+
}
42+
43+
func (s *DigestComputer) Reset() error {
44+
if 1 != C.X_EVP_DigestInit_ex(s.ctx, s.evpMD.c(), engineRef(s.engine)) {
45+
return fmt.Errorf("openssl: %v: cannot init evpMD ctx", s.evpMD.String())
46+
}
47+
return nil
48+
}
49+
50+
func (s *DigestComputer) Write(p []byte) (n int, err error) {
51+
if len(p) == 0 {
52+
return 0, nil
53+
}
54+
if 1 != C.X_EVP_DigestUpdate(s.ctx, unsafe.Pointer(&p[0]),
55+
C.size_t(len(p))) {
56+
return 0, fmt.Errorf("openssl: %v: cannot update evpMD", s.evpMD.String())
57+
}
58+
return len(p), nil
59+
}
60+
61+
func (s *DigestComputer) Sum() ([]byte, error) {
62+
result := make([]byte, s.evpMD.Size())
63+
if 1 != C.X_EVP_DigestFinal_ex(s.ctx,
64+
(*C.uchar)(unsafe.Pointer(&result[0])), nil) {
65+
return result, fmt.Errorf("openssl: %v: cannot finalize ctx", s.evpMD.String())
66+
}
67+
return result, s.Reset()
68+
}

‎engine.go

+7
Original file line numberDiff line numberDiff line change
@@ -48,3 +48,10 @@ func EngineById(name string) (*Engine, error) {
4848
})
4949
return e, nil
5050
}
51+
52+
func engineRef(e *Engine) *C.ENGINE {
53+
if e == nil {
54+
return nil
55+
}
56+
return e.e
57+
}

‎evp_md.go

+356
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,356 @@
1+
package openssl
2+
3+
// #include "openssl/opensslv.h"
4+
// #include "shim.h"
5+
import "C"
6+
7+
// EVP_MD represents hash function implemented by OpenSSL
8+
type EVP_MD int
9+
10+
const (
11+
EVP_NULL EVP_MD = iota
12+
EVP_MD5
13+
EVP_MD4
14+
EVP_SHA
15+
EVP_SHA1
16+
EVP_DSS
17+
EVP_DSS1
18+
EVP_MDC2
19+
EVP_RIPEMD160
20+
EVP_SHA224
21+
EVP_SHA256
22+
EVP_SHA384
23+
EVP_SHA512
24+
EVP_SHA512_224
25+
EVP_SHA512_256
26+
EVP_BLAKE2B_512
27+
EVP_BLAKE2S_256
28+
EVP_GOST
29+
EVP_MD2
30+
EVP_SHA3_224
31+
EVP_SHA3_256
32+
EVP_SHA3_384
33+
EVP_SHA3_512
34+
EVP_SHAKE128
35+
EVP_SHAKE256
36+
EVP_SM3
37+
EVP_WHIRLPOOL
38+
)
39+
40+
// Size returns the size of the digest
41+
func (evp EVP_MD) Size() int {
42+
var bits int
43+
switch evp {
44+
case EVP_BLAKE2B_512:
45+
bits = 512
46+
case EVP_BLAKE2S_256:
47+
bits = 256
48+
case EVP_GOST:
49+
bits = 256
50+
case EVP_MD2:
51+
bits = 128
52+
case EVP_MD4:
53+
bits = 128
54+
case EVP_MD5:
55+
bits = 128
56+
case EVP_RIPEMD160:
57+
bits = 160
58+
case EVP_SHA1:
59+
bits = 160
60+
case EVP_SHA224:
61+
bits = 224
62+
case EVP_SHA256:
63+
bits = 256
64+
case EVP_SHA384:
65+
bits = 384
66+
case EVP_SHA512:
67+
bits = 512
68+
case EVP_SHA512_224:
69+
bits = 224
70+
case EVP_SHA512_256:
71+
bits = 256
72+
case EVP_SHA3_224:
73+
bits = 224
74+
case EVP_SHA3_256:
75+
bits = 256
76+
case EVP_SHA3_384:
77+
bits = 384
78+
case EVP_SHA3_512:
79+
bits = 512
80+
case EVP_SHAKE128:
81+
bits = 128
82+
case EVP_SHAKE256:
83+
bits = 256
84+
case EVP_SM3:
85+
bits = 256
86+
}
87+
return bits / 8
88+
}
89+
90+
// Size returns hash function block size in bytes
91+
func (evp EVP_MD) BlockSize() int {
92+
var bits int
93+
switch evp {
94+
case EVP_BLAKE2B_512:
95+
bits = 1024
96+
case EVP_BLAKE2S_256:
97+
bits = 512
98+
case EVP_GOST:
99+
bits = 256
100+
case EVP_MD2:
101+
bits = 128
102+
case EVP_MD4:
103+
bits = 512
104+
case EVP_MD5:
105+
bits = 512
106+
case EVP_RIPEMD160:
107+
bits = 512
108+
case EVP_SHA1:
109+
bits = 512
110+
case EVP_SHA224:
111+
bits = 512
112+
case EVP_SHA256:
113+
bits = 512
114+
case EVP_SHA384:
115+
bits = 1024
116+
case EVP_SHA512:
117+
bits = 1024
118+
case EVP_SHA512_224:
119+
bits = 1024
120+
case EVP_SHA512_256:
121+
bits = 1024
122+
case EVP_SHA3_224:
123+
bits = 1124
124+
case EVP_SHA3_256:
125+
bits = 1088
126+
case EVP_SHA3_384:
127+
bits = 832
128+
case EVP_SHA3_512:
129+
bits = 576
130+
case EVP_SHAKE128:
131+
bits = 1344
132+
case EVP_SHAKE256:
133+
bits = 1088
134+
case EVP_SM3:
135+
bits = 512
136+
}
137+
return bits / 8
138+
}
139+
140+
func (evp EVP_MD) String() string {
141+
switch evp {
142+
case EVP_BLAKE2B_512:
143+
return "BLAKE2B_512"
144+
case EVP_BLAKE2S_256:
145+
return "BLAKE2S_256"
146+
case EVP_GOST:
147+
return "GOST"
148+
case EVP_MD2:
149+
return "MD2"
150+
case EVP_MD4:
151+
return "MD4"
152+
case EVP_MD5:
153+
return "MD5"
154+
case EVP_RIPEMD160:
155+
return "RMD160"
156+
case EVP_SHA1:
157+
return "SHA1"
158+
case EVP_SHA224:
159+
return "SHA224"
160+
case EVP_SHA256:
161+
return "SHA256"
162+
case EVP_SHA384:
163+
return "SHA384"
164+
case EVP_SHA512:
165+
return "SHA512"
166+
case EVP_SHA512_224:
167+
return "SHA512_224"
168+
case EVP_SHA512_256:
169+
return "SHA512_256"
170+
case EVP_SHA3_224:
171+
return "SHA3_224"
172+
case EVP_SHA3_256:
173+
return "SHA3_256"
174+
case EVP_SHA3_384:
175+
return "SHA3_384"
176+
case EVP_SHA3_512:
177+
return "SHA3_512"
178+
case EVP_SHAKE128:
179+
return "SHAKE128"
180+
case EVP_SHAKE256:
181+
return "SHAKE256"
182+
case EVP_SM3:
183+
return "SM3"
184+
default:
185+
return "UNKNOWN"
186+
}
187+
}
188+
189+
190+
/*
191+
OpenSSL compatibility table:
192+
193+
1.1.1 -> 0x1010100fL
194+
1.1.0 -> 0x1010000fL
195+
196+
Digest 1.0.2 1.1.0 1.1.1
197+
BLAKE2B512 - + +
198+
BLAKE2S256 - + +
199+
GOST - + +
200+
MD2 - + +
201+
MD4 + + +
202+
MD5 + + +
203+
RIPEMD160 + + +
204+
SHA1 + + +
205+
SHA224 + + +
206+
SHA256 + + +
207+
SHA384 + + +
208+
SHA512 + + +
209+
SHA512-224 - - +
210+
SHA512-256 - - +
211+
SHA3-224 - - +
212+
SHA3-256 - - +
213+
SHA3-384 - - +
214+
SHA3-512 - - +
215+
SHAKE128 - - +
216+
SHAKE256 - - +
217+
SM3 - - +
218+
WHIRLPOOL + + +
219+
*/
220+
221+
var hashFunctionsOpenSSLv111 = map[EVP_MD]bool{
222+
EVP_BLAKE2B_512: true,
223+
EVP_BLAKE2S_256: true,
224+
EVP_GOST: true,
225+
EVP_MD2: true,
226+
EVP_MD4: true,
227+
EVP_MD5: true,
228+
EVP_RIPEMD160: true,
229+
EVP_SHA1: true,
230+
EVP_SHA224: true,
231+
EVP_SHA256: true,
232+
EVP_SHA384: true,
233+
EVP_SHA512: true,
234+
EVP_SHA512_224: true,
235+
EVP_SHA512_256: true,
236+
EVP_SHA3_224: true,
237+
EVP_SHA3_256: true,
238+
EVP_SHA3_384: true,
239+
EVP_SHA3_512: true,
240+
EVP_SHAKE128: true,
241+
EVP_SHAKE256: true,
242+
EVP_SM3: true,
243+
EVP_WHIRLPOOL: true,
244+
}
245+
246+
var hashFunctionsOpenSSLv110 = map[EVP_MD]bool{
247+
EVP_BLAKE2B_512: true,
248+
EVP_BLAKE2S_256: true,
249+
EVP_GOST: true,
250+
EVP_MD2: true,
251+
EVP_MD4: true,
252+
EVP_MD5: true,
253+
EVP_RIPEMD160: true,
254+
EVP_SHA1: true,
255+
EVP_SHA224: true,
256+
EVP_SHA256: true,
257+
EVP_SHA384: true,
258+
EVP_SHA512: true,
259+
EVP_SHA512_224: false,
260+
EVP_SHA512_256: false,
261+
EVP_SHA3_224: false,
262+
EVP_SHA3_256: false,
263+
EVP_SHA3_384: false,
264+
EVP_SHA3_512: false,
265+
EVP_SHAKE128: false,
266+
EVP_SHAKE256: false,
267+
EVP_SM3: false,
268+
EVP_WHIRLPOOL: true,
269+
}
270+
271+
var hashFunctionsOpenSSLv102 = map[EVP_MD]bool{
272+
EVP_BLAKE2B_512: false,
273+
EVP_BLAKE2S_256: false,
274+
EVP_GOST: false,
275+
EVP_MD2: false,
276+
EVP_MD4: true,
277+
EVP_MD5: true,
278+
EVP_RIPEMD160: true,
279+
EVP_SHA1: true,
280+
EVP_SHA224: true,
281+
EVP_SHA256: true,
282+
EVP_SHA384: true,
283+
EVP_SHA512: true,
284+
EVP_SHA512_224: false,
285+
EVP_SHA512_256: false,
286+
EVP_SHA3_224: false,
287+
EVP_SHA3_256: false,
288+
EVP_SHA3_384: false,
289+
EVP_SHA3_512: false,
290+
EVP_SHAKE128: false,
291+
EVP_SHAKE256: false,
292+
EVP_SM3: false,
293+
EVP_WHIRLPOOL: true,
294+
}
295+
296+
// Supported checks if this hash function is supported by the installed version of OpenSSL
297+
func (evp EVP_MD) Supported() bool {
298+
if C.OPENSSL_VERSION_NUMBER >= 0x1010100f {
299+
return hashFunctionsOpenSSLv111[evp]
300+
} else if C.OPENSSL_VERSION_NUMBER >= 0x1010000f {
301+
return hashFunctionsOpenSSLv110[evp]
302+
}
303+
return hashFunctionsOpenSSLv102[evp]
304+
}
305+
306+
// c returns pointer to the struct that is used during digest initialization
307+
func (evp EVP_MD) c() (evpMD *C.EVP_MD) {
308+
switch evp {
309+
case EVP_BLAKE2B_512:
310+
evpMD = C.X_EVP_blake2b512()
311+
case EVP_BLAKE2S_256:
312+
evpMD = C.X_EVP_blake2s256()
313+
case EVP_GOST:
314+
panic("Not implemented yet")
315+
case EVP_MD2:
316+
evpMD = C.X_EVP_md2()
317+
case EVP_MD4:
318+
evpMD = C.X_EVP_md4()
319+
case EVP_MD5:
320+
evpMD = C.X_EVP_md5()
321+
case EVP_RIPEMD160:
322+
evpMD = C.X_EVP_ripemd160()
323+
case EVP_SHA1:
324+
evpMD = C.X_EVP_sha1()
325+
case EVP_SHA224:
326+
evpMD = C.X_EVP_sha224()
327+
case EVP_SHA256:
328+
evpMD = C.X_EVP_sha256()
329+
case EVP_SHA384:
330+
evpMD = C.X_EVP_sha384()
331+
case EVP_SHA512:
332+
evpMD = C.X_EVP_sha512()
333+
case EVP_SHA512_224:
334+
evpMD = C.X_EVP_sha512_224()
335+
case EVP_SHA512_256:
336+
evpMD = C.X_EVP_sha512_256()
337+
case EVP_SHA3_224:
338+
evpMD = C.X_EVP_sha3_224()
339+
case EVP_SHA3_256:
340+
evpMD = C.X_EVP_sha3_256()
341+
case EVP_SHA3_384:
342+
evpMD = C.X_EVP_sha3_384()
343+
case EVP_SHA3_512:
344+
evpMD = C.X_EVP_sha3_512()
345+
case EVP_SHAKE128:
346+
evpMD = C.X_EVP_shake128()
347+
case EVP_SHAKE256:
348+
evpMD = C.X_EVP_shake256()
349+
case EVP_SM3:
350+
panic("Not implemented yet")
351+
default:
352+
panic("Not implemented yet")
353+
}
354+
return
355+
}
356+

‎md4.go

+9-45
Original file line numberDiff line numberDiff line change
@@ -17,63 +17,27 @@ package openssl
1717
// #include "shim.h"
1818
import "C"
1919

20-
import (
21-
"errors"
22-
"runtime"
23-
"unsafe"
24-
)
25-
2620
type MD4Hash struct {
27-
ctx *C.EVP_MD_CTX
28-
engine *Engine
21+
*DigestComputer
2922
}
3023

3124
func NewMD4Hash() (*MD4Hash, error) { return NewMD4HashWithEngine(nil) }
3225

3326
func NewMD4HashWithEngine(e *Engine) (*MD4Hash, error) {
34-
hash := &MD4Hash{engine: e}
35-
hash.ctx = C.X_EVP_MD_CTX_new()
36-
if hash.ctx == nil {
37-
return nil, errors.New("openssl: md4: unable to allocate ctx")
38-
}
39-
runtime.SetFinalizer(hash, func(hash *MD4Hash) { hash.Close() })
40-
if err := hash.Reset(); err != nil {
27+
dc, err := NewDigestComputerWithEngine(e, EVP_MD4)
28+
if err != nil {
4129
return nil, err
4230
}
43-
return hash, nil
44-
}
45-
46-
func (s *MD4Hash) Close() {
47-
if s.ctx != nil {
48-
C.X_EVP_MD_CTX_free(s.ctx)
49-
s.ctx = nil
50-
}
51-
}
52-
53-
func (s *MD4Hash) Reset() error {
54-
if 1 != C.X_EVP_DigestInit_ex(s.ctx, C.X_EVP_md4(), engineRef(s.engine)) {
55-
return errors.New("openssl: md4: cannot init digest ctx")
56-
}
57-
return nil
58-
}
59-
60-
func (s *MD4Hash) Write(p []byte) (n int, err error) {
61-
if len(p) == 0 {
62-
return 0, nil
63-
}
64-
if 1 != C.X_EVP_DigestUpdate(s.ctx, unsafe.Pointer(&p[0]),
65-
C.size_t(len(p))) {
66-
return 0, errors.New("openssl: md4: cannot update digest")
67-
}
68-
return len(p), nil
31+
return &MD4Hash{DigestComputer: dc}, nil
6932
}
7033

7134
func (s *MD4Hash) Sum() (result [16]byte, err error) {
72-
if 1 != C.X_EVP_DigestFinal_ex(s.ctx,
73-
(*C.uchar)(unsafe.Pointer(&result[0])), nil) {
74-
return result, errors.New("openssl: md4: cannot finalize ctx")
35+
sum, err := s.DigestComputer.Sum()
36+
if err != nil {
37+
return
7538
}
76-
return result, s.Reset()
39+
copy(result[:], sum)
40+
return
7741
}
7842

7943
func MD4(data []byte) (result [16]byte, err error) {

‎md4_test.go

+10-2
Original file line numberDiff line numberDiff line change
@@ -120,9 +120,17 @@ func benchmarkMD4(b *testing.B, length int64, fn md4func) {
120120
}
121121

122122
func BenchmarkMD4Large_openssl(b *testing.B) {
123-
benchmarkMD4(b, 1024*1024, func(buf []byte) { MD4(buf) })
123+
benchmarkMD4(b, 1024*1024, func(buf []byte) {
124+
if _, err := MD4(buf); err != nil {
125+
b.Fatal(err)
126+
}
127+
})
124128
}
125129

126130
func BenchmarkMD4Small_openssl(b *testing.B) {
127-
benchmarkMD4(b, 1, func(buf []byte) { MD4(buf) })
131+
benchmarkMD4(b, 1, func(buf []byte) {
132+
if _, err := MD4(buf); err != nil {
133+
b.Fatal(err)
134+
}
135+
})
128136
}

‎md5.go

+9-45
Original file line numberDiff line numberDiff line change
@@ -17,63 +17,27 @@ package openssl
1717
// #include "shim.h"
1818
import "C"
1919

20-
import (
21-
"errors"
22-
"runtime"
23-
"unsafe"
24-
)
25-
2620
type MD5Hash struct {
27-
ctx *C.EVP_MD_CTX
28-
engine *Engine
21+
*DigestComputer
2922
}
3023

3124
func NewMD5Hash() (*MD5Hash, error) { return NewMD5HashWithEngine(nil) }
3225

3326
func NewMD5HashWithEngine(e *Engine) (*MD5Hash, error) {
34-
hash := &MD5Hash{engine: e}
35-
hash.ctx = C.X_EVP_MD_CTX_new()
36-
if hash.ctx == nil {
37-
return nil, errors.New("openssl: md5: unable to allocate ctx")
38-
}
39-
runtime.SetFinalizer(hash, func(hash *MD5Hash) { hash.Close() })
40-
if err := hash.Reset(); err != nil {
27+
dc, err := NewDigestComputerWithEngine(e, EVP_MD5)
28+
if err != nil {
4129
return nil, err
4230
}
43-
return hash, nil
44-
}
45-
46-
func (s *MD5Hash) Close() {
47-
if s.ctx != nil {
48-
C.X_EVP_MD_CTX_free(s.ctx)
49-
s.ctx = nil
50-
}
51-
}
52-
53-
func (s *MD5Hash) Reset() error {
54-
if 1 != C.X_EVP_DigestInit_ex(s.ctx, C.X_EVP_md5(), engineRef(s.engine)) {
55-
return errors.New("openssl: md5: cannot init digest ctx")
56-
}
57-
return nil
58-
}
59-
60-
func (s *MD5Hash) Write(p []byte) (n int, err error) {
61-
if len(p) == 0 {
62-
return 0, nil
63-
}
64-
if 1 != C.X_EVP_DigestUpdate(s.ctx, unsafe.Pointer(&p[0]),
65-
C.size_t(len(p))) {
66-
return 0, errors.New("openssl: md5: cannot update digest")
67-
}
68-
return len(p), nil
31+
return &MD5Hash{DigestComputer: dc}, nil
6932
}
7033

7134
func (s *MD5Hash) Sum() (result [16]byte, err error) {
72-
if 1 != C.X_EVP_DigestFinal_ex(s.ctx,
73-
(*C.uchar)(unsafe.Pointer(&result[0])), nil) {
74-
return result, errors.New("openssl: md5: cannot finalize ctx")
35+
sum, err := s.DigestComputer.Sum()
36+
if err != nil {
37+
return
7538
}
76-
return result, s.Reset()
39+
copy(result[:], sum)
40+
return
7741
}
7842

7943
func MD5(data []byte) (result [16]byte, err error) {

‎sha1.go

+9-52
Original file line numberDiff line numberDiff line change
@@ -17,70 +17,27 @@ package openssl
1717
// #include "shim.h"
1818
import "C"
1919

20-
import (
21-
"errors"
22-
"runtime"
23-
"unsafe"
24-
)
25-
2620
type SHA1Hash struct {
27-
ctx *C.EVP_MD_CTX
28-
engine *Engine
21+
*DigestComputer
2922
}
3023

3124
func NewSHA1Hash() (*SHA1Hash, error) { return NewSHA1HashWithEngine(nil) }
3225

3326
func NewSHA1HashWithEngine(e *Engine) (*SHA1Hash, error) {
34-
hash := &SHA1Hash{engine: e}
35-
hash.ctx = C.X_EVP_MD_CTX_new()
36-
if hash.ctx == nil {
37-
return nil, errors.New("openssl: sha1: unable to allocate ctx")
38-
}
39-
runtime.SetFinalizer(hash, func(hash *SHA1Hash) { hash.Close() })
40-
if err := hash.Reset(); err != nil {
27+
dc, err := NewDigestComputerWithEngine(e, EVP_SHA1)
28+
if err != nil {
4129
return nil, err
4230
}
43-
return hash, nil
44-
}
45-
46-
func (s *SHA1Hash) Close() {
47-
if s.ctx != nil {
48-
C.X_EVP_MD_CTX_free(s.ctx)
49-
s.ctx = nil
50-
}
51-
}
52-
53-
func engineRef(e *Engine) *C.ENGINE {
54-
if e == nil {
55-
return nil
56-
}
57-
return e.e
58-
}
59-
60-
func (s *SHA1Hash) Reset() error {
61-
if 1 != C.X_EVP_DigestInit_ex(s.ctx, C.X_EVP_sha1(), engineRef(s.engine)) {
62-
return errors.New("openssl: sha1: cannot init digest ctx")
63-
}
64-
return nil
65-
}
66-
67-
func (s *SHA1Hash) Write(p []byte) (n int, err error) {
68-
if len(p) == 0 {
69-
return 0, nil
70-
}
71-
if 1 != C.X_EVP_DigestUpdate(s.ctx, unsafe.Pointer(&p[0]),
72-
C.size_t(len(p))) {
73-
return 0, errors.New("openssl: sha1: cannot update digest")
74-
}
75-
return len(p), nil
31+
return &SHA1Hash{DigestComputer: dc}, nil
7632
}
7733

7834
func (s *SHA1Hash) Sum() (result [20]byte, err error) {
79-
if 1 != C.X_EVP_DigestFinal_ex(s.ctx,
80-
(*C.uchar)(unsafe.Pointer(&result[0])), nil) {
81-
return result, errors.New("openssl: sha1: cannot finalize ctx")
35+
sum, err := s.DigestComputer.Sum()
36+
if err != nil {
37+
return
8238
}
83-
return result, s.Reset()
39+
copy(result[:], sum)
40+
return
8441
}
8542

8643
func SHA1(data []byte) (result [20]byte, err error) {

‎sha256.go

+9-45
Original file line numberDiff line numberDiff line change
@@ -17,63 +17,27 @@ package openssl
1717
// #include "shim.h"
1818
import "C"
1919

20-
import (
21-
"errors"
22-
"runtime"
23-
"unsafe"
24-
)
25-
2620
type SHA256Hash struct {
27-
ctx *C.EVP_MD_CTX
28-
engine *Engine
21+
*DigestComputer
2922
}
3023

3124
func NewSHA256Hash() (*SHA256Hash, error) { return NewSHA256HashWithEngine(nil) }
3225

3326
func NewSHA256HashWithEngine(e *Engine) (*SHA256Hash, error) {
34-
hash := &SHA256Hash{engine: e}
35-
hash.ctx = C.X_EVP_MD_CTX_new()
36-
if hash.ctx == nil {
37-
return nil, errors.New("openssl: sha256: unable to allocate ctx")
38-
}
39-
runtime.SetFinalizer(hash, func(hash *SHA256Hash) { hash.Close() })
40-
if err := hash.Reset(); err != nil {
27+
dc, err := NewDigestComputerWithEngine(e, EVP_SHA256)
28+
if err != nil {
4129
return nil, err
4230
}
43-
return hash, nil
44-
}
45-
46-
func (s *SHA256Hash) Close() {
47-
if s.ctx != nil {
48-
C.X_EVP_MD_CTX_free(s.ctx)
49-
s.ctx = nil
50-
}
51-
}
52-
53-
func (s *SHA256Hash) Reset() error {
54-
if 1 != C.X_EVP_DigestInit_ex(s.ctx, C.X_EVP_sha256(), engineRef(s.engine)) {
55-
return errors.New("openssl: sha256: cannot init digest ctx")
56-
}
57-
return nil
58-
}
59-
60-
func (s *SHA256Hash) Write(p []byte) (n int, err error) {
61-
if len(p) == 0 {
62-
return 0, nil
63-
}
64-
if 1 != C.X_EVP_DigestUpdate(s.ctx, unsafe.Pointer(&p[0]),
65-
C.size_t(len(p))) {
66-
return 0, errors.New("openssl: sha256: cannot update digest")
67-
}
68-
return len(p), nil
31+
return &SHA256Hash{DigestComputer: dc}, nil
6932
}
7033

7134
func (s *SHA256Hash) Sum() (result [32]byte, err error) {
72-
if 1 != C.X_EVP_DigestFinal_ex(s.ctx,
73-
(*C.uchar)(unsafe.Pointer(&result[0])), nil) {
74-
return result, errors.New("openssl: sha256: cannot finalize ctx")
35+
sum, err := s.DigestComputer.Sum()
36+
if err != nil {
37+
return
7538
}
76-
return result, s.Reset()
39+
copy(result[:], sum)
40+
return
7741
}
7842

7943
func SHA256(data []byte) (result [32]byte, err error) {

‎shim.c

+98-6
Original file line numberDiff line numberDiff line change
@@ -598,26 +598,50 @@ const EVP_MD *X_EVP_md_null() {
598598
return EVP_md_null();
599599
}
600600

601-
const EVP_MD *X_EVP_md5() {
602-
return EVP_md5();
601+
const EVP_MD *X_EVP_blake2b512() {
602+
#if OPENSSL_VERSION_NUMBER >= 0x1010000fL
603+
return EVP_blake2b512();
604+
#else
605+
return NULL;
606+
#endif
607+
}
608+
609+
const EVP_MD *X_EVP_blake2s256() {
610+
#if OPENSSL_VERSION_NUMBER >= 0x1010000fL
611+
return EVP_blake2s256();
612+
#else
613+
return NULL;
614+
#endif
615+
}
616+
617+
const EVP_MD *X_EVP_md2() {
618+
#if OPENSSL_VERSION_NUMBER >= 0x1010000fL
619+
return EVP_md2();
620+
#else
621+
return NULL;
622+
#endif
603623
}
604624

605625
const EVP_MD *X_EVP_md4() {
606626
return EVP_md4();
607627
}
608628

609-
const EVP_MD *X_EVP_ripemd160() {
610-
return EVP_ripemd160();
629+
const EVP_MD *X_EVP_md5() {
630+
return EVP_md5();
611631
}
612632

613-
const EVP_MD *X_EVP_sha224() {
614-
return EVP_sha224();
633+
const EVP_MD *X_EVP_ripemd160() {
634+
return EVP_ripemd160();
615635
}
616636

617637
const EVP_MD *X_EVP_sha1() {
618638
return EVP_sha1();
619639
}
620640

641+
const EVP_MD *X_EVP_sha224() {
642+
return EVP_sha224();
643+
}
644+
621645
const EVP_MD *X_EVP_sha256() {
622646
return EVP_sha256();
623647
}
@@ -630,6 +654,74 @@ const EVP_MD *X_EVP_sha512() {
630654
return EVP_sha512();
631655
}
632656

657+
const EVP_MD *X_EVP_sha512_224() {
658+
#if OPENSSL_VERSION_NUMBER >= 0x1010100fL
659+
return EVP_sha512_224();
660+
#else
661+
return NULL;
662+
#endif
663+
}
664+
665+
const EVP_MD *X_EVP_sha512_256() {
666+
#if OPENSSL_VERSION_NUMBER >= 0x1010100fL
667+
return EVP_sha512_256();
668+
#else
669+
return NULL;
670+
#endif
671+
}
672+
673+
const EVP_MD *X_EVP_sha3_224() {
674+
#if OPENSSL_VERSION_NUMBER >= 0x1010100fL
675+
return EVP_sha3_224();
676+
#else
677+
return NULL;
678+
#endif
679+
}
680+
681+
const EVP_MD *X_EVP_sha3_256() {
682+
#if OPENSSL_VERSION_NUMBER >= 0x1010100fL
683+
return EVP_sha3_256();
684+
#else
685+
return NULL;
686+
#endif
687+
}
688+
689+
const EVP_MD *X_EVP_sha3_384() {
690+
#if OPENSSL_VERSION_NUMBER >= 0x1010100fL
691+
return EVP_sha3_384();
692+
#else
693+
return NULL;
694+
#endif
695+
}
696+
697+
const EVP_MD *X_EVP_sha3_512() {
698+
#if OPENSSL_VERSION_NUMBER >= 0x1010100fL
699+
return EVP_sha3_512();
700+
#else
701+
return NULL;
702+
#endif
703+
}
704+
705+
const EVP_MD *X_EVP_shake128() {
706+
#if OPENSSL_VERSION_NUMBER >= 0x1010100fL
707+
return EVP_shake128();
708+
#else
709+
return NULL;
710+
#endif
711+
}
712+
713+
const EVP_MD *X_EVP_shake256() {
714+
#if OPENSSL_VERSION_NUMBER >= 0x1010100fL
715+
return EVP_shake256();
716+
#else
717+
return NULL;
718+
#endif
719+
}
720+
721+
const EVP_MD *X_EVP_whirlpool() {
722+
return EVP_whirlpool();
723+
}
724+
633725
int X_EVP_MD_size(const EVP_MD *md) {
634726
return EVP_MD_size(md);
635727
}

‎shim.h

+12-1
Original file line numberDiff line numberDiff line change
@@ -108,8 +108,9 @@ extern const EVP_MD *X_EVP_get_digestbyname(const char *name);
108108
extern EVP_MD_CTX *X_EVP_MD_CTX_new();
109109
extern void X_EVP_MD_CTX_free(EVP_MD_CTX *ctx);
110110
extern const EVP_MD *X_EVP_md_null();
111-
extern const EVP_MD *X_EVP_md5();
111+
extern const EVP_MD *X_EVP_md2();
112112
extern const EVP_MD *X_EVP_md4();
113+
extern const EVP_MD *X_EVP_md5();
113114
extern const EVP_MD *X_EVP_sha();
114115
extern const EVP_MD *X_EVP_sha1();
115116
extern const EVP_MD *X_EVP_dss();
@@ -119,6 +120,16 @@ extern const EVP_MD *X_EVP_sha224();
119120
extern const EVP_MD *X_EVP_sha256();
120121
extern const EVP_MD *X_EVP_sha384();
121122
extern const EVP_MD *X_EVP_sha512();
123+
extern const EVP_MD *X_EVP_sha512_224();
124+
extern const EVP_MD *X_EVP_sha512_256();
125+
extern const EVP_MD *X_EVP_sha3_224();
126+
extern const EVP_MD *X_EVP_sha3_256();
127+
extern const EVP_MD *X_EVP_sha3_384();
128+
extern const EVP_MD *X_EVP_sha3_512();
129+
extern const EVP_MD *X_EVP_blake2b512();
130+
extern const EVP_MD *X_EVP_blake2s256();
131+
extern const EVP_MD *X_EVP_shake128();
132+
extern const EVP_MD *X_EVP_shake256();
122133
extern int X_EVP_MD_size(const EVP_MD *md);
123134
extern int X_EVP_DigestInit_ex(EVP_MD_CTX *ctx, const EVP_MD *type, ENGINE *impl);
124135
extern int X_EVP_DigestUpdate(EVP_MD_CTX *ctx, const void *d, size_t cnt);

0 commit comments

Comments
 (0)
Please sign in to comment.