Skip to content

Commit ede4f81

Browse files
committed
feat(x509) export pubkey
1 parent d19ece9 commit ede4f81

File tree

9 files changed

+110
-3470
lines changed

9 files changed

+110
-3470
lines changed

README.md

+5-4
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ Description
2323
supports OpenSSL `1.1.1`, `1.1.0` and `1.0.2` series.
2424

2525
The API is kept as same [luaossl](https://github.com/wahern/luaossl) while only a small sets
26-
of OpenSSL API implemented.
26+
of OpenSSL APIs are currently implemented.
2727

2828

2929
[Back to TOC](#table-of-contents)
@@ -163,7 +163,8 @@ Module to expose BIGNUM structure. This module is not exposed through `resty.ope
163163

164164
### bn.new
165165

166-
**syntax**: *b, err = bn.new(bn_instance or number?)*
166+
**syntax**: *b, err = bn.new(bn_cdata?)*
167+
**syntax**: *b, err = bn.new(number?)*
167168

168169
Creates a BIGNUM instance. The first argument can be `BIGNUM *` cdata object, or a Lua number,
169170
or `nil` to creates a empty instance.
@@ -189,8 +190,8 @@ Module to interact with message digest.
189190

190191
**syntax**: *d, err = digest.new(digest_name)*
191192

192-
Creates a digest instance. The `digest_name` is a valid digest algorithm name. To view
193-
a list of digest algorithms implemented, use `openssl list -digest-algorithms`
193+
Creates a digest instance.`digest_name` is a string of digest algorithm name. To view
194+
a list of digest algorithms implemented, use `openssl list -digest-algorithms`.
194195

195196
### digest:update
196197

lib/resty/openssl/bn.lua

+12-1
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,8 @@ ffi.cdef(
4040
]]
4141
)
4242

43+
local bn_ptr_ct = ffi.typeof('BIGNUM*')
44+
4345
function _M.new(bn)
4446
local _bn
4547
if bn == nil or type(bn) == 'number'then
@@ -52,6 +54,11 @@ function _M.new(bn)
5254
end
5355
end
5456
elseif type(bn) == 'cdata' then
57+
if ffi.istype(bn_ptr_ct, bn) then
58+
ctx = bn
59+
else
60+
return nil, "expect a BIGNUM* cdata at #1"
61+
end
5562
_bn = bn
5663
else
5764
return nil, "unexpected initializer passed in (got " .. type(bn) .. ")"
@@ -60,13 +67,17 @@ function _M.new(bn)
6067
return setmetatable( { bn = _bn }, mt), nil
6168
end
6269

70+
function _M.istype(l)
71+
return l.ctx and ffi.istype(bn_ptr_ct, l.ctx)
72+
end
73+
6374
function _M:toBinary()
6475
local length = (C.BN_num_bits(self.bn)+7)/8
6576
length = floor(length)
6677
local buf = ffi_new('unsigned char[?]', length)
6778
local sz = C.BN_bn2bin(self.bn, buf)
6879
if sz == 0 then
69-
return nil, format_error("bn.toBinary")
80+
return nil, format_error("bn:toBinary")
7081
end
7182
buf = ffi_str(buf, length)
7283
return buf, nil

lib/resty/openssl/pkey.lua

+26-20
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ require "resty.openssl.ec"
1313
local bn_lib = require "resty.openssl.bn"
1414
require "resty.openssl.bio"
1515
require "resty.openssl.pem"
16+
require "resty.openssl.objects"
1617
local util = require "resty.openssl.util"
1718
require "resty.openssl.x509"
1819
local format_error = require("resty.openssl.err").format_error
@@ -188,39 +189,41 @@ local PEM_write_bio_PrivateKey_args = { null, null, 0, null, null }
188189
local PEM_write_bio_PUBKEY_args = {}
189190

190191
local function tostring(self, fmt)
191-
local method
192+
local method, args
192193
if fmt == 'private' or fmt == 'PrivateKey' then
193194
method = 'PEM_write_bio_PrivateKey'
195+
args = PEM_write_bio_PrivateKey_args
194196
elseif not fmt or fmt == 'public' or fmt == 'PublicKey' then
195197
method = 'PEM_write_bio_PUBKEY'
198+
args = PEM_write_bio_PUBKEY_args
196199
else
197200
return nil, "can only export private or public key, not " .. fmt
198201
end
199202

200-
local args
201-
if method == 'PEM_write_bio_PrivateKey' then
202-
args = PEM_write_bio_PrivateKey_args
203-
else
204-
args = PEM_write_bio_PUBKEY_args
205-
end
206-
207203
return util.read_using_bio(method, self.ctx, unpack(args))
208204
end
209205

210206
local _M = {}
211207
local mt = { __index = _M, __tostring = tostring }
212208

209+
local evp_ptr_ct = ffi.typeof('EVP_PKEY*')
213210
-- type
214211
-- bits
215212
-- exp
216213
-- curve
217214
function _M.new(s, ...)
218-
local ctx, err, has_private
215+
local ctx, err
219216
s = s or {}
220217
if type(s) == 'table' then
221218
ctx, err = generate_key(s)
222219
elseif type(s) == 'string' then
223220
ctx, err = load_pkey(s, ...)
221+
elseif type(s) == 'cdata' then
222+
if ffi.istype(evp_ptr_ct, s) then
223+
ctx = s
224+
else
225+
return nil, "expect a EVP_PKEY* cdata at #1"
226+
end
224227
else
225228
return nil, "unexpected type " .. type(s) .. " at #1"
226229
end
@@ -237,7 +240,6 @@ function _M.new(s, ...)
237240

238241
local self = setmetatable({
239242
ctx = ctx,
240-
-- has_private = has_private,
241243
key_size = key_size,
242244
}, mt)
243245

@@ -246,8 +248,12 @@ function _M.new(s, ...)
246248
return self, nil
247249
end
248250

251+
function _M.istype(l)
252+
return l.ctx and ffi.istype(evp_ptr_ct, l.ctx)
253+
end
254+
249255
local empty_table = {}
250-
local bnptr_type = ffi.typeof("const BIGNUM *[1]")
256+
local bn_ptrptr_ct = ffi.typeof("const BIGNUM *[1]")
251257
local function get_rsa_params_11(pkey)
252258
-- {"n", "e", "d", "p", "q", "dmp1", "dmq1", "iqmp"}
253259
local rsa_st = C.EVP_PKEY_get0_RSA(pkey)
@@ -258,17 +264,17 @@ local function get_rsa_params_11(pkey)
258264
return setmetatable(empty_table, {
259265
__index = function(tbl, k)
260266
if k == 'n' then
261-
local bnptr = bnptr_type()
262-
C.RSA_get0_key(rsa_st, bnptr, nil, nil)
263-
return bn_lib.new(bnptr[0]), nil
267+
local ptr = bn_ptrptr_ct()
268+
C.RSA_get0_key(rsa_st, ptr, nil, nil)
269+
return bn_lib.new(ptr[0]), nil
264270
elseif k == 'e' then
265-
local bnptr = bnptr_type()
266-
C.RSA_get0_key(rsa_st, nil, bnptr, nil)
267-
return bn_lib.new(bnptr[0]), nil
271+
local ptr = bn_ptrptr_ct()
272+
C.RSA_get0_key(rsa_st, nil, ptr, nil)
273+
return bn_lib.new(ptr[0]), nil
268274
elseif k == 'd' then
269-
local bnptr = bnptr_type()
270-
C.RSA_get0_key(rsa_st, nil, nil, bnptr)
271-
return bn_lib.new(bnptr[0]), nil
275+
local ptr = bn_ptrptr_ct()
276+
C.RSA_get0_key(rsa_st, nil, nil, ptr)
277+
return bn_lib.new(ptr[0]), nil
272278
end
273279
end
274280
}), nil

lib/resty/openssl/x509/init.lua

+11
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ local OPENSSL_10 = require("resty.openssl.version").OPENSSL_10
1717

1818
ffi.cdef [[
1919
void X509_free(X509 *a);
20+
EVP_PKEY *X509_get_pubkey(X509 *x);
2021

2122
EVP_PKEY *d2i_PrivateKey_bio(BIO *bp, EVP_PKEY **a);
2223
EVP_PKEY *d2i_PUBKEY_bio(BIO *bp, EVP_PKEY **a);
@@ -150,4 +151,14 @@ function _M:getLifetime()
150151
return not_before, not_after, nil
151152
end
152153

154+
function _M:getPublicKey()
155+
local ctx = C.X509_get_pubkey(self.ctx)
156+
if ctx == nil then
157+
return nil, format_error("x509:getPublicKey")
158+
end
159+
-- lazy load pkey to avoid circular dependency (which might makes pkey a userdata)
160+
local pkey_lib = require("resty.openssl.pkey")
161+
return pkey_lib.new(ctx)
162+
end
163+
153164
return _M

0 commit comments

Comments
 (0)