Skip to content

Commit e092646

Browse files
committed
chore(utils): better caching of crypto primitives and move to non-deprecated crypto
1 parent 5fbd183 commit e092646

File tree

2 files changed

+115
-57
lines changed

2 files changed

+115
-57
lines changed

Changes.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ All notable changes to `lua-resty-session` will be documented in this file.
1414
### Changed
1515
- chore(utils): safer utils.is_fips_mode (fix #176)
1616
- chore(session): a bit more relaxed assertions (fix #175)
17+
- chore(utils): better caching of crypto primitives and move to non-deprecated crypto
1718

1819

1920
## [4.0.5] - 2023-08-16

lib/resty/session/utils.lua

Lines changed: 114 additions & 57 deletions
Original file line numberDiff line numberDiff line change
@@ -480,34 +480,56 @@ end
480480

481481

482482
local derive_hkdf_sha256 do
483-
local kdf_derive
483+
local kdf
484+
local hkdf_extract
485+
local hkdf_expand
484486

485487
local EXTRACTED_KEYS = {}
486488

487489
local HKDF_SHA256_EXTRACT_OPTS
488490
local HKDF_SHA256_EXPAND_OPTS
489491

490492
local function derive_hkdf_sha256_real(ikm, nonce, usage, size)
491-
local err
492-
local key = EXTRACTED_KEYS[ikm]
493+
local key, err, _ = EXTRACTED_KEYS[ikm]
493494
if not key then
494-
HKDF_SHA256_EXTRACT_OPTS.hkdf_key = ikm
495-
key, err = kdf_derive(HKDF_SHA256_EXTRACT_OPTS)
496-
HKDF_SHA256_EXTRACT_OPTS.hkdf_key = ""
495+
if not hkdf_extract then
496+
hkdf_extract, err = kdf.new("HKDF")
497+
if not hkdf_extract then
498+
return nil, err
499+
end
500+
end
501+
502+
HKDF_SHA256_EXTRACT_OPTS.key = ikm
503+
key, err = hkdf_extract:derive(32, HKDF_SHA256_EXTRACT_OPTS)
504+
HKDF_SHA256_EXTRACT_OPTS.key = ""
497505
if not key then
506+
hkdf_extract = nil
498507
return nil, err
499508
end
500509
EXTRACTED_KEYS[ikm] = key
501510
end
502511

503-
HKDF_SHA256_EXPAND_OPTS.hkdf_key = key
504-
HKDF_SHA256_EXPAND_OPTS.hkdf_info = usage .. ":" .. nonce
505-
HKDF_SHA256_EXPAND_OPTS.outlen = size
506-
key, err = kdf_derive(HKDF_SHA256_EXPAND_OPTS)
512+
if not hkdf_expand then
513+
hkdf_expand, err = kdf.new("HKDF")
514+
if not hkdf_expand then
515+
return nil, err
516+
end
517+
end
518+
519+
HKDF_SHA256_EXPAND_OPTS.key = key
520+
HKDF_SHA256_EXPAND_OPTS.info = usage .. ":" .. nonce
521+
522+
key, err = hkdf_expand:derive(size or 44, HKDF_SHA256_EXPAND_OPTS)
507523
if not key then
524+
hkdf_expand = nil
508525
return nil, err
509526
end
510527

528+
_, err = hkdf_expand:reset()
529+
if err then
530+
hkdf_expand = nil
531+
end
532+
511533
return key
512534
end
513535

@@ -528,27 +550,22 @@ local derive_hkdf_sha256 do
528550
-- local nonce = utils.rand_bytes(32)
529551
-- local key, err = utils.derive_hkdf_sha256(ikm, nonce, "encryption", 32)
530552
derive_hkdf_sha256 = function(ikm, nonce, usage, size)
531-
if not kdf_derive then
532-
local kdf = require("resty.openssl.kdf")
553+
if not kdf then
554+
kdf = require("resty.openssl.kdf")
533555
HKDF_SHA256_EXTRACT_OPTS = {
534-
type = kdf.HKDF,
535-
outlen = 32,
536-
md = "sha256",
556+
digest = "sha256",
557+
mode = kdf.HKDEF_MODE_EXTRACT_ONLY,
558+
key = "",
537559
salt = "",
538-
hkdf_key = "",
539-
hkdf_mode = kdf.HKDEF_MODE_EXTRACT_ONLY,
540-
hkdf_info = "",
560+
info = "",
541561
}
542562
HKDF_SHA256_EXPAND_OPTS = {
543-
type = kdf.HKDF,
544-
outlen = 44,
545-
md = "sha256",
563+
digest = "sha256",
564+
mode = kdf.HKDEF_MODE_EXPAND_ONLY,
565+
key = "",
546566
salt = "",
547-
hkdf_key = "",
548-
hkdf_mode = kdf.HKDEF_MODE_EXPAND_ONLY,
549-
hkdf_info = "",
567+
info = "",
550568
}
551-
kdf_derive = kdf.derive
552569
end
553570
derive_hkdf_sha256 = derive_hkdf_sha256_real
554571
return derive_hkdf_sha256(ikm, nonce, usage, size)
@@ -557,20 +574,35 @@ end
557574

558575

559576
local derive_pbkdf2_hmac_sha256 do
560-
local kdf_derive
577+
local kdf
578+
local pbkdf2
561579

562580
local PBKDF2_SHA256_OPTS
563581

564582
local function derive_pbkdf2_hmac_sha256_real(pass, salt, usage, size, iterations)
565-
PBKDF2_SHA256_OPTS.pass = pass
583+
local _, err, key
584+
if not pbkdf2 then
585+
pbkdf2, err = kdf.new("PBKDF2")
586+
if err then
587+
return nil, err
588+
end
589+
end
590+
591+
PBKDF2_SHA256_OPTS.iter = iterations or 10000
566592
PBKDF2_SHA256_OPTS.salt = usage .. ":" .. salt
567-
PBKDF2_SHA256_OPTS.outlen = size
568-
PBKDF2_SHA256_OPTS.pbkdf2_iter = iterations
569-
local key, err = kdf_derive(PBKDF2_SHA256_OPTS)
593+
PBKDF2_SHA256_OPTS.pass = pass
594+
595+
key, err = pbkdf2:derive(size or 44, PBKDF2_SHA256_OPTS)
570596
if not key then
597+
pbkdf2 = nil
571598
return nil, err
572599
end
573600

601+
_, err = pbkdf2:reset()
602+
if err then
603+
pbkdf2 = nil
604+
end
605+
574606
return key
575607
end
576608

@@ -592,17 +624,14 @@ local derive_pbkdf2_hmac_sha256 do
592624
-- local salt = utils.rand_bytes(32)
593625
-- local key, err = utils.derive_pbkdf2_hmac_sha256(pass, salt, "encryption", 32, 10000)
594626
derive_pbkdf2_hmac_sha256 = function(pass, salt, usage, size, iterations)
595-
if not kdf_derive then
596-
local kdf = require("resty.openssl.kdf")
627+
if not kdf then
628+
kdf = require("resty.openssl.kdf")
597629
PBKDF2_SHA256_OPTS = {
598-
type = kdf.PBKDF2,
599-
outlen = 44,
600-
md = "sha256",
601-
pass = "",
630+
digest = "sha256",
631+
iter = 10000,
602632
salt = "",
603-
pbkdf2_iter = 10000,
633+
pass = "",
604634
}
605-
kdf_derive = kdf.derive
606635
end
607636
derive_pbkdf2_hmac_sha256 = derive_pbkdf2_hmac_sha256_real
608637
return derive_pbkdf2_hmac_sha256(pass, salt, usage, size, iterations)
@@ -690,26 +719,44 @@ end
690719

691720

692721
local encrypt_aes_256_gcm, decrypt_aes_256_gcm do
722+
local cipher
723+
local cipher_encrypt
724+
local cipher_decrypt
725+
693726
local AES_256_GCP_CIPHER = "aes-256-gcm"
694727
local AES_256_GCM_TAG_SIZE = 16
695728

696-
local cipher_aes_256_gcm
697729
local function encrypt_aes_256_gcm_real(key, iv, plaintext, aad)
698-
local ciphertext, err = cipher_aes_256_gcm:encrypt(key, iv, plaintext, false, aad)
730+
if not cipher_encrypt then
731+
cipher_encrypt = cipher.new(AES_256_GCP_CIPHER)
732+
end
733+
734+
local ciphertext, err = cipher_encrypt:encrypt(key, iv, plaintext, false, aad)
699735
if not ciphertext then
736+
cipher_encrypt = nil
700737
return nil, err
701738
end
702739

703-
local tag, err = cipher_aes_256_gcm:get_aead_tag(AES_256_GCM_TAG_SIZE)
740+
local tag, err = cipher_encrypt:get_aead_tag(AES_256_GCM_TAG_SIZE)
704741
if not tag then
742+
cipher_encrypt = nil
705743
return nil, err
706744
end
707745

708746
return ciphertext, nil, tag
709747
end
710748

711749
local function decrypt_aes_256_gcm_real(key, iv, ciphertext, aad, tag)
712-
return cipher_aes_256_gcm:decrypt(key, iv, ciphertext, false, aad, tag)
750+
if not cipher_decrypt then
751+
cipher_decrypt = cipher.new(AES_256_GCP_CIPHER)
752+
end
753+
754+
local plaintext, err = cipher_decrypt:decrypt(key, iv, ciphertext, false, aad, tag)
755+
if not plaintext then
756+
cipher_decrypt = nil
757+
end
758+
759+
return plaintext, err
713760
end
714761

715762
---
@@ -731,8 +778,8 @@ local encrypt_aes_256_gcm, decrypt_aes_256_gcm do
731778
-- local key, err, iv = utils.derive_aes_gcm_256_key_and_iv(ikm, nonce)
732779
-- local enc, err, tag = utils.encrypt_aes_256_gcm(key, iv, "hello", "[email protected]")
733780
encrypt_aes_256_gcm = function(key, iv, plaintext, aad)
734-
if not cipher_aes_256_gcm then
735-
cipher_aes_256_gcm = require("resty.openssl.cipher").new(AES_256_GCP_CIPHER)
781+
if not cipher then
782+
cipher = require("resty.openssl.cipher")
736783
end
737784
encrypt_aes_256_gcm = encrypt_aes_256_gcm_real
738785
return encrypt_aes_256_gcm(key, iv, plaintext, aad)
@@ -744,10 +791,10 @@ local encrypt_aes_256_gcm, decrypt_aes_256_gcm do
744791
-- @function utils.decrypt_aes_256_gcm
745792
-- @tparam string key encryption key
746793
-- @tparam string iv initialization vector
747-
-- @tparam string plaintext plain text
794+
-- @tparam string ciphertext plain text
748795
-- @tparam string aad additional authenticated data
749796
-- @tparam string tag authentication tag
750-
-- @treturn string|nil ciphertext
797+
-- @treturn string|nil plaintext
751798
-- @treturn string|nil error message
752799
--
753800
-- @usage
@@ -758,8 +805,8 @@ local encrypt_aes_256_gcm, decrypt_aes_256_gcm do
758805
-- local enc, err, tag = utils.encrypt_aes_256_gcm(key, iv, "hello", "[email protected]")
759806
-- local out, err = utils.decrypt_aes_256_gcm(key, iv, ciphertext, "[email protected]", tag)
760807
decrypt_aes_256_gcm = function(key, iv, ciphertext, aad, tag)
761-
if not cipher_aes_256_gcm then
762-
cipher_aes_256_gcm = require("resty.openssl.cipher").new(AES_256_GCP_CIPHER)
808+
if not cipher then
809+
cipher = require("resty.openssl.cipher")
763810
end
764811
decrypt_aes_256_gcm = decrypt_aes_256_gcm_real
765812
return decrypt_aes_256_gcm(key, iv, ciphertext, aad, tag)
@@ -768,21 +815,31 @@ end
768815

769816

770817
local hmac_sha256 do
818+
local mac
771819
local hmac
772-
local HMAC_SHA256_DIGEST = "sha256"
820+
local MAC_MAC = "HMAC"
821+
local MAC_DIGEST = "sha256"
773822

774823
local function hmac_sha256_real(key, value)
775-
local mac, err = hmac.new(key, HMAC_SHA256_DIGEST)
776-
if not mac then
777-
return nil, err
824+
local _, err, output
825+
if not hmac then
826+
hmac, err = mac.new(key, MAC_MAC, nil, MAC_DIGEST)
827+
if err then
828+
return nil, err
829+
end
778830
end
779831

780-
local digest, err = mac:final(value)
781-
if not digest then
832+
output, err = hmac:final(value)
833+
if not output then
782834
return nil, err
783835
end
784836

785-
return digest
837+
_, err = hmac:reset()
838+
if err then
839+
hmac = nil
840+
end
841+
842+
return output
786843
end
787844

788845
---
@@ -801,8 +858,8 @@ local hmac_sha256 do
801858
-- local key, err = utils.derive_hmac_sha256_key(ikm, nonce)
802859
-- local mac, err = utils.hmac_sha256(key, "hello")
803860
hmac_sha256 = function(key, value)
804-
if not hmac then
805-
hmac = require("resty.openssl.hmac")
861+
if not mac then
862+
mac = require("resty.openssl.mac")
806863
end
807864
hmac_sha256 = hmac_sha256_real
808865
return hmac_sha256(key, value)

0 commit comments

Comments
 (0)