-
-
Notifications
You must be signed in to change notification settings - Fork 1.6k
/
digest.cr
85 lines (69 loc) · 1.83 KB
/
digest.cr
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
require "../lib_crypto"
require "./digest_base"
module OpenSSL
class Digest
class Error < OpenSSL::Error; end
class UnsupportedError < Error; end
include DigestBase
getter name : String
def initialize(@name, @ctx : LibCrypto::EVP_MD_CTX)
raise Error.new("Invalid EVP_MD_CTX") unless @ctx
end
protected def self.new_evp_mt_ctx(name)
md = LibCrypto.evp_get_digestbyname(name)
unless md
raise UnsupportedError.new("Unsupported digest algorithm: #{name}")
end
ctx = LibCrypto.evp_md_ctx_new
unless ctx
raise Error.new "Digest initialization failed."
end
if LibCrypto.evp_digestinit_ex(ctx, md, nil) != 1
raise Error.new "Digest initialization failed."
end
ctx
end
def self.new(name)
new(name, new_evp_mt_ctx(name))
end
def finalize
LibCrypto.evp_md_ctx_free(self)
end
def clone
ctx = LibCrypto.evp_md_ctx_new
if LibCrypto.evp_md_ctx_copy(ctx, @ctx) == 0
LibCrypto.evp_md_ctx_free(ctx)
raise Error.new("Unable to clone digest")
end
Digest.new(@name, ctx)
end
def reset
if LibCrypto.evp_digestinit_ex(self, to_unsafe_md, nil) != 1
raise Error.new "Digest initialization failed."
end
self
end
def update(data : String | Slice)
LibCrypto.evp_digestupdate(self, data, data.size)
self
end
protected def finish
size = digest_size
data = Pointer(UInt8).malloc(size)
LibCrypto.evp_digestfinal_ex(@ctx, data, nil)
data.to_slice(size)
end
def digest_size
LibCrypto.evp_md_size(to_unsafe_md)
end
def block_size
LibCrypto.evp_md_block_size(to_unsafe_md)
end
def to_unsafe_md
LibCrypto.evp_md_ctx_md(self)
end
def to_unsafe
@ctx
end
end
end