Alnyli07 commented on code in PR #13165:
URL: https://github.com/apache/apisix/pull/13165#discussion_r3171214319


##########
apisix/plugins/dpop.lua:
##########
@@ -0,0 +1,1384 @@
+local core = require("apisix.core")
+local cjson = require("cjson.safe")
+local resty_sha256 = require("resty.sha256")
+local http = require("resty.http")
+local openssl_pkey = require("resty.openssl.pkey")
+local lrucache = require("resty.lrucache")
+local ngx = ngx
+
+local plugin_name = "dpop"
+
+-- Module-level local JTI cache — fallback when ngx.shared.dpop_jti_cache
+-- is not configured. Per-worker only; ensures fail-closed per RFC 9449 §11.1.
+local _jti_local_cache = {}
+local _jti_local_count = 0
+
+local function jti_local_cleanup()
+    local now = ngx.time()
+    local new_count = 0
+    for k, expiry in pairs(_jti_local_cache) do
+        if expiry <= now then
+            _jti_local_cache[k] = nil
+        else
+            new_count = new_count + 1
+        end
+    end
+    _jti_local_count = new_count
+end
+
+-- PKey LRU cache: JWK JSON → openssl pkey object
+-- 128 entries is generous — typical deployment has 1-3 signing keys
+local _pkey_cache, pkey_cache_err = lrucache.new(128)
+if not _pkey_cache then
+    error("failed to create pkey LRU cache: " .. (pkey_cache_err or "unknown"))
+end
+
+-- Module-level JWKS caches
+local _jwks_cache = {}           -- jwks_uri -> { keys_by_kid = {kid -> 
jwk_table}, fetched_at }
+local _discovery_cache = {}      -- discovery_url -> { jwks_uri, fetched_at }
+local _jwks_last_refetch = 0     -- rate limit: max 1 refetch per 60s
+
+-- Introspection cache: module-level local fallback when 
ngx.shared.dpop_intro_cache
+-- is not configured. Per-worker only; shared dict preferred for cross-worker 
consistency.
+local _introspection_cache = {}
+local _introspection_cache_count = 0
+
+-- Infinispan digest auth nonce cache (per-worker)
+local _ispn_digest_cache = {}  -- endpoint -> { nonce, realm, qop, nc }
+
+-- HTTP Digest Auth helper: parse WWW-Authenticate header and compute 
Authorization
+local function ispn_digest_auth(www_auth, method, uri, username, password)
+    if not www_auth then return nil end
+    local realm = www_auth:match('realm="([^"]+)"')
+    local nonce = www_auth:match('nonce="([^"]+)"')
+    local qop   = www_auth:match('qop="([^"]*)"') or www_auth:match('qop=([^,% 
]+)')
+    if not realm or not nonce then return nil end
+    local nc = "00000001"
+    local cnonce = ngx.md5(tostring(ngx.now()) .. tostring(math.random(1, 
999999)))
+    local ha1 = ngx.md5(username .. ":" .. realm .. ":" .. password)
+    local ha2 = ngx.md5(method .. ":" .. uri)
+    local response
+    if qop and qop:find("auth") then
+        response = ngx.md5(ha1 .. ":" .. nonce .. ":" .. nc
+            .. ":" .. cnonce .. ":" .. "auth" .. ":" .. ha2)
+    else
+        response = ngx.md5(ha1 .. ":" .. nonce .. ":" .. ha2)
+    end
+    return 'Digest username="' .. username
+        .. '", realm="' .. realm
+        .. '", nonce="' .. nonce
+        .. '", uri="' .. uri
+        .. '", qop=auth, nc=' .. nc
+        .. ', cnonce="' .. cnonce
+        .. '", response="' .. response .. '"',
+        nonce, realm, qop
+end
+
+local schema = {
+    type = "object",
+    properties = {
+        allowed_algs = {
+            type = "array",
+            items = {
+                type = "string",
+                enum = {
+                    "ES256", "ES384", "ES512",
+                    "RS256", "RS384", "RS512",
+                    "PS256", "PS384", "PS512",
+                },

Review Comment:
   **75f2d87** : the verification path now dispatches all nine asymmetric algs 
declared
   in the schema: ES256/384/512, RS256/384/512, PS256/384/512.
   
   Two implementation notes:
   
   1. ECDSA proofs carry signatures in raw R||S (JWS Compact). Converting
      to the DER form OpenSSL expects needs long-form SEQUENCE length once
      R+S exceeds 127 bytes (every ES512 signature). The `raw_ecdsa_to_der`
      helper now emits long-form (`0x81`/`0x82`).
   2. RSA-PSS verification under OpenSSL 3's provider API requires
      `RSA_PKCS1_PSS_PADDING` to be set before any saltlen/MGF1 parameter.
      The plugin now passes padding via the dedicated argument and uses
      the named `pss_saltlen` setter (digest length per RFC 7518 §3.5),
      so parameters are applied in the order the provider enforces.
   
   **0028e83** : TEST 31 (ES512) and TEST 32-35 (RS384/RS512/PS384/PS512) cover 
the
   newly-added algorithms. The full suite has 35 cases / 105 assertions
   and passes against the standard upstream test runner.



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]

Reply via email to