Skip to content
Merged
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
36 changes: 32 additions & 4 deletions src/OpenSSL.jl
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ export TLSv12ClientMethod, TLSv12ServerMethod,
EvpEncNull, EvpBlowFishCBC, EvpBlowFishECB, EvpBlowFishCFB, EvpBlowFishOFB, EvpAES128CBC,
EvpAES128ECB, EvpAES128CFB, EvpAES128OFB, EvpMDNull, EvpMD2, EvpMD5, EvpSHA1, EvpDSS1,
encrypt_init, cipher, add_extension, add_extensions, decrypt_init, digest_init, digest_update, digest_final,
digest, random_bytes, rsa_generate_key, dsa_generate_key, add_entry, sign_certificate, sign_request, adjust,
digest, hmac, random_bytes, rsa_generate_key, dsa_generate_key, add_entry, sign_certificate, sign_request, adjust,
add_cert, unpack, eof, isreadable, iswritable, bytesavailable, read, unsafe_write, connect,
get_peer_certificate, free, HTTP2_ALPN, UPDATE_HTTP2_ALPN, version

Expand Down Expand Up @@ -1291,6 +1291,34 @@ function digest(evp_digest::EvpDigest, io::IO)
return result
end


"""
Compute the hash-based message authentication code of the given data using a key and a hash function.
"""
function hmac(evp_digest::EvpDigest, in_data::AbstractVector{UInt8}, key::AbstractVector{UInt8})::Vector{UInt8}
out_data = Vector{UInt8}(undef, EVP_MAX_MD_SIZE)
out_length = Ref{UInt32}(0)
GC.@preserve key in_data out_data out_length begin
if ccall(
(:HMAC, libcrypto),
Ptr{Cchar},
(EvpDigest, Ptr{Cvoid}, Cint, Ptr{Cchar}, Csize_t, Ptr{Cchar}, Ptr{Cuint}),
evp_digest,
pointer(key), length(key),
pointer(in_data), length(in_data),
pointer(out_data), pointer_from_objref(out_length)) == C_NULL
throw(OpenSSLError())
end
end
resize!(out_data, out_length.x)
return out_data
end

hmac(evp_digest::EvpDigest, in_data::AbstractString, key::AbstractString)::Vector{UInt8} = hmac(evp_digest, codeunits(in_data), codeunits(key))
hmac(evp_digest::EvpDigest, in_data::AbstractString, key::AbstractVector{UInt8})::Vector{UInt8} = hmac(evp_digest, codeunits(in_data), key)



"""
RSA structure.
The RSA structure consists of several BIGNUM components.
Expand Down Expand Up @@ -1454,7 +1482,7 @@ end

"""
ec_generate_key(nid)

Generate EC key pair from a curve identifier. See ec_builtin_curves().

"""
Expand Down Expand Up @@ -1954,7 +1982,7 @@ mutable struct EvpPKey

function EvpPKey(ec::EC)::EvpPKey
evp_pkey = EvpPKey()

if ccall(
(:EVP_PKEY_assign, libcrypto),
Cint, (EvpPKey, Cint, EC),
Expand All @@ -1963,7 +1991,7 @@ mutable struct EvpPKey
ec) != 1
throw(OpenSSLError())
end

ec.ec = C_NULL
return evp_pkey
end
Expand Down
15 changes: 13 additions & 2 deletions test/runtests.jl
Original file line number Diff line number Diff line change
Expand Up @@ -277,6 +277,17 @@ end
@test bytes2hex(digest(OpenSSL.EvpRIPEMD160(), IOBuffer("abc"))) == "8eb208f7e05d987a9b044a8e98c6b087f15a0bfc"
end

@testset "HMAC" begin
# echo -n "Hello world" | openssl dgst -sha256 -mac hmac -macopt hexkey:01020304
@test bytes2hex(hmac(OpenSSL.EvpSHA256(), "Hello world", hex2bytes("01020304"))) == "760e94f3d42452f372885f22d3ed5915ffa5a7d6ddf38716331f9c2786f21e5a"

# echo -n "Hello world" | openssl dgst -sha512 -hmac "Σλ"
@test bytes2hex(hmac(OpenSSL.EvpSHA512(), "Hello world", "Σλ")) == "dfe48de81d0f5f8976d20e10c6fa2f82ff3cc28ae5060b396f70e26d45563a4cfa446d53d5fbea377018b54dac1ec368c979fb2b4a99f642cb0a2d8422c3bfa6"

# echo -n "Hello world" | openssl dgst -sha256 -hmac ""
@test bytes2hex(hmac(OpenSSL.EvpSHA256(), [0x48, 0x65, 0x6c, 0x6c, 0x6f, 0x20, 0x77, 0x6f, 0x72, 0x6c, 0x64], b"")) == "c50d316a00f927059322a898ea2fa7321fdb4d32eb749656ea7ba7775a870dc0"
end

@testset "SelfSignedCertificate" begin
x509_certificate = X509Certificate()

Expand Down Expand Up @@ -675,8 +686,8 @@ end

@testset "CACertsLoading" begin
certs_dir = joinpath(@__DIR__, "certs")
certs_path = joinpath(certs_dir, "ca-certificates.crt")
certs_path = joinpath(certs_dir, "ca-certificates.crt")

ssl_method = OpenSSL.TLSClientMethod()
ctx = OpenSSL.SSLContext(ssl_method, certs_path)
@test typeof(ctx) == OpenSSL.SSLContext
Expand Down
Loading