Skip to content

Commit

Permalink
feat(pkey) allow pkey.new to compose from parameters
Browse files Browse the repository at this point in the history
  • Loading branch information
fffonion committed May 27, 2024
1 parent 0016308 commit 91a30f6
Show file tree
Hide file tree
Showing 4 changed files with 124 additions and 3 deletions.
24 changes: 23 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -872,13 +872,14 @@ for EC keys. See [pkey:sign](#pkeysign) and [pkey.verify](#pkeyverify) for detai
- When running outside of OpenResty, needs to install a JSON library (`cjson` or `dkjson`)
and `basexx`.

[Back to TOC](#table-of-contents)

#### Key generation

**syntax**: *pk, err = pkey.new(config?)*

Generate a new public key or private key.


To generate RSA key, `config` table can have `bits` and `exp` field to control key generation.
When `config` is emitted, this function generates a 2048 bit RSA key with `exponent` of 65537,
which is equivalent to:
Expand Down Expand Up @@ -937,6 +938,27 @@ pkey.new({

```

[Back to TOC](#table-of-contents)

#### Key composition

**syntax**: *pk, err = pkey.new(config?)*

Compose a public or private key using existing parameters. To see
list of parameters for each key, refer to [pkey:set_parameters](#pkeyset_parameters).

Only `type` and `params` should exist in `config` table, all other keys will be ignored.

```lua
local private_bn = require "resty.openssl.bn".new("7F48282CCA4C1A65D589C06DBE9C42AE50FBFFDF3A18CBB48498E1DE47F11BE1A3486CD8FA950D68F111970F922279D8", 16)
local p_384, err = assert(require("resty.openssl.pkey").new({
type = "EC",
params = {
private = private_bn,
group = "secp384r1",
}
}))
```

[Back to TOC](#table-of-contents)

Expand Down
1 change: 1 addition & 0 deletions lib/resty/openssl/auxiliary/jwk.lua
Original file line number Diff line number Diff line change
Expand Up @@ -177,6 +177,7 @@ function _M.load_jwk(txt)
if key ~= nil then
return key
end
key_free = function() end
else
return nil, "not yet supported jwk type \"" .. (tbl["kty"] or "nil") .. "\""
end
Expand Down
69 changes: 67 additions & 2 deletions lib/resty/openssl/pkey.lua
Original file line number Diff line number Diff line change
Expand Up @@ -402,6 +402,67 @@ local function generate_key(config)
return ctx_ptr[0]
end

local function compose_key(config)
local typ = config.type or 'RSA'
local key_type

if typ == "RSA" then
key_type = evp_macro.EVP_PKEY_RSA
elseif typ == "EC" then
key_type = evp_macro.EVP_PKEY_EC
elseif evp_macro.ecx_curves[typ] then
key_type = evp_macro.ecx_curves[typ]
else
return nil, "unsupported type " .. typ
end
if key_type == 0 then
return nil, "the linked OpenSSL library doesn't support " .. typ .. " key"
end

local key, err, key_free, _

if key_type == evp_macro.EVP_PKEY_EC then
key = C.EC_KEY_new()
if key == nil then
return nil, "EC_KEY_new failed"
end
key_free = C.EC_KEY_free
_, err = ec_lib.set_parameters(key, config.params)
elseif key_type == evp_macro.EVP_PKEY_RSA then
key = C.RSA_new()
if key == nil then
return nil, "RSA_new failed"
end
key_free = C.RSA_free
_, err = rsa_lib.set_parameters(key, config.params)
elseif key_type == evp_macro.EVP_PKEY_ED25519 or
key_type == evp_macro.EVP_PKEY_X25519 or
key_type == evp_macro.EVP_PKEY_ED448 or
key_type == evp_macro.EVP_PKEY_X448 then
key_free = function() end
key, err = ecx_lib.set_parameters(key_type, nil, config.params)
end

if err then
return nil, "failed to construct " .. typ.. " key from parameters: " .. err
end

local ctx = C.EVP_PKEY_new()
if ctx == nil then
key_free(key)
return nil, "EVP_PKEY_new() failed"
end

local code = C.EVP_PKEY_assign(ctx, key_type, key)
if code ~= 1 then
key_free(key)
C.EVP_PKEY_free(ctx)
return nil, "EVP_PKEY_assign() failed"
end

return ctx
end

local load_key_try_funcs = {} do
-- TODO: pkcs1 load functions are not required in openssl 3.0
local _load_key_try_funcs = {
Expand Down Expand Up @@ -506,9 +567,13 @@ function _M.new(s, opts)
local ctx, err
s = s or {}
if type(s) == 'table' then
ctx, err = generate_key(s)
if s.params then
ctx, err = compose_key(s)
else
ctx, err = generate_key(s)
end
if err then
err = "pkey.new:generate_key: " .. err
err = "pkey.new:new_key: " .. err
end
elseif type(s) == 'string' then
ctx, err = load_pem_der(s, opts or empty_table, load_key_try_funcs)
Expand Down
33 changes: 33 additions & 0 deletions t/openssl/pkey.t
Original file line number Diff line number Diff line change
Expand Up @@ -225,6 +225,39 @@ nil



=== TEST 9: compose: Compose key from parameters
--- http_config eval: $::HttpConfig
--- config
location =/t {
content_by_lua_block {
local p_384 = myassert(require("resty.openssl.pkey").new({
type = "EC",
"ec_paramgen_curve:secp384r1",
}))
local out = myassert(p_384:to_PEM('private'))
local params = p_384:get_parameters()
local newp_384, err = myassert(require("resty.openssl.pkey").new({
type = "EC",
params = {
private = params.private,
public = params.public,
group = params.group
}
}))
local out2 = myassert(newp_384:to_PEM('private'))
ngx.say(out == out2)
}
}
--- request
GET /t
--- response_body
true
--- no_error_log
[error]



=== TEST 9: paramgen: Outpus DH and EC params
--- http_config eval: $::HttpConfig
--- config
Expand Down

0 comments on commit 91a30f6

Please sign in to comment.