python-jose JWE在AWS Lambda中报错:无法找到密钥匹配算法
问题
开发认证系统时使用python-jose库的jwe.encrypt()加密信息,本地运行正常,但部署到AWS Lambda后报错。已尝试更换Python运行时版本至3.8.10、更换加密密钥,问题仍未解决。
加密函数
def generate_jwe_token(data: dict): data["exp"] = int(time.time()) + 86700 token = jwe.encrypt( plaintext=str(data), key="1114A78B79D5C91189E2D4BD4C1F6" ) return token
Serverless依赖层配置
pythonRequirements: useStaticCache: false cacheLocation: "/temp_pip" slim: false layer: name: ${self:provider.stage}-login-api compatibleRuntimes: - python3.7 - python3.8 licenseInfo: GPLv3 allowedAccounts: - "*" noDeploy: - pylint - coverage - autopep8
依赖清单
boto3==1.17.40 botocore==1.20.112 mysql-connector-python==8.0.22 aws-secretsmanager-caching==1.1.1.5 six==1.16.0 urllib3==1.26.12 pytest==7.1.2 pytest-cov python-jose==3.3.0 cffi==1.15.1 cryptography==39.0.1 ecdsa==0.18.0 pyasn1==0.4.8 pycparser==2.21 rsa==4.9
错误栈
[ERROR] JWKError: Unable to find an algorithm for key: b'1114A78B79D5C91189E2D4BD4C1F6' Traceback (most recent call last): File "/var/task/functions/secret_token_rotation/rotation_token.py", line 47, in lambda_handler create_secret(service_client, arn, token) File "/var/task/functions/commons/rotation_steps.py", line 57, in create_secret token_credential = generate_jwe_token(data) File "/var/task/functions/commons/rotation_steps.py", line 166, in generate_jwe_token key="1114A78B79D5C91189E2D4BD4C1F6" File "/opt/python/jose/jwe.py", line 54, in encrypt enc_cek, iv, cipher_text, auth_tag = _encrypt_and_auth(key, algorithm, encryption, zip, plaintext, encoded_header) File "/opt/python/jose/jwe.py", line 391, in _encrypt_and_auth encryption_key = jwk.construct(cek_bytes, enc) File "/opt/python/jose/jwk.py", line 78, in construct raise JWKError("Unable to find an algorithm for key: %s" % key_data)
错误成因及解决办法
成因
- 密钥格式与算法不匹配:直接传入字符串密钥时,未明确指定加密算法,python-jose会自动尝试匹配,但本地与Lambda环境的依赖版本差异(尤其是cryptography)导致算法匹配逻辑不一致;同时当前密钥长度不符合默认算法的要求。
- 依赖版本兼容性问题:python-jose 3.3.0与cryptography 39.0.1存在兼容性冲突,部分加密算法的支持逻辑在Lambda环境中无法正常工作。
- 依赖构建环境差异:本地构建的依赖可能包含与Lambda(Amazon Linux)不兼容的二进制文件,导致加密相关功能失效。
解决步骤
1. 明确指定加密算法并使用合规密钥
JWE加密需明确指定算法,推荐使用对称加密算法A256GCM,且密钥必须为32字节(256位)的原始字节或Base64编码字符串。修改加密函数如下:
import jose.jwe import jose.constants import base64 import time def generate_jwe_token(data: dict): data["exp"] = int(time.time()) + 86700 # 使用32字节的Base64编码密钥(实际需从AWS Secrets Manager读取,避免硬编码) key_bytes = base64.b64decode("MTExNEE3OEI3OUQ1QzkxMTg5RTJENkJENDQxRjYxMjM0NTY3ODkwMQ==") token = jose.jwe.encrypt( plaintext=str(data), key=key_bytes, algorithm=jose.constants.Algorithms.DIR, encryption=jose.constants.Algorithms.A256GCM ) return token
2. 调整依赖版本至兼容组合
更新依赖清单,使用与cryptography兼容的python-jose版本:
python-jose[cryptography]==3.4.0 cryptography==38.0.4
3. 用Lambda兼容环境构建依赖层
使用Amazon Linux容器构建依赖,避免二进制兼容性问题:
docker run -v "$PWD":/var/task public.ecr.aws/sam/build-python3.8:latest pip install -r requirements.txt -t python/lib/python3.8/site-packages/
再通过Serverless部署该依赖层。
4. 避免硬编码密钥
将密钥存储在AWS Secrets Manager中,在Lambda函数运行时动态读取,提升安全性同时避免编码传递问题。
内容的提问来源于stack exchange,提问作者Sebatian Ayala
相关产品推荐
相关产品推荐

