我正在使用 AWS KMS 非对称 ECC (ES256) 密钥在 Python3 中使用 API 调用来签名和验证令牌。响应返回
{
"KeyId": "arn:aws:kms:us-east-1:000000000000:key/1234",
"Signature": "b'0D\\x02 \\x18\\xd9\\x13\\x96\\x9d\\xb00p\\xc9H\\'-\\xc6@{\\xd1V\\xf5\\xeb\\x83\"1\\x0e:\\x98\\xb4\\xea6P\\x0f\\xdf\\x82\\x02 \\x1fPt\\xc0\\x81pB\\xaa\\xe7_\\xf2~\\x91BlU\\x05\\xba1\\xe0\\xfe\\xf6\\xe4\\xebL\\nl\\xfc\\xf8\\xce\\xc6_'",
"SigningAlgorithm": "ECDSA_SHA_256"
}
如果我使用 AWS CLI,则响应“签名”是 base64 编码的:
{
"KeyId": "arn:aws:kms:us-east-1:000000000000:key/1234",
"Signature": "MEQCIBqjAiAnMKkugooWU6/AqCyfhQUocoiVeIIf8lL2p7YbAiBEJOl2cp9HzQNufiMBezIjZuSGW6ID13l7JSzTgLlv+g==",
"SigningAlgorithm": "ECDSA_SHA_256"
}
每当我尝试base64.urlsafe_b64encode(string)
使用 Python3 中的 API 响应对“签名”进行 base64 编码时,我都无法验证签名。这是我收到的错误示例:
调用验证操作时发生错误(InvalidKeyUsageException):asn1:结构错误:标签不匹配(16 vs {class:1 tag:2 length:39 isCompound:true}){optional:false explicit:false application:false private:false defaultValue: tag: stringType:0 timeType:0 set:false omitEmpty:false} ecdsaSignature @2
如何对从 API 返回的“签名”字节字符串进行 base64 编码并且仍然能够验证?
更新:
如果我更新到base64.b4encode
而不是base64.urlsafe_encode
我得到相同的结果:
def _sign_token(self, key_id, message):
signature = kms_client.sign(
KeyId=key_id,
Message=message,
MessageType="RAW",
SigningAlgorithm="ECDSA_SHA_256",
)
logger.log(msg=signature, level=cl.log_level)
return base64.b64encode(signature["Signature"]).decode()
日志消息返回:
{“asctime”:“2021-04-03 19:40:27,593”,“levelname”:“INFO”,“name”:“util.sign”,“lineno”:214,“message”:null,“env ": "local", "KeyId": "arn:aws:kms:us-east-1:000000000000:key/309d8dc5-409e-4f57-96a8-c71223c84dc2", "签名": "b'0E\x02!\ x00\xcc\x82\xf4$@?\x9e\n\xd7$\x94\x9f.\x1d5\x19{W\x1e\xcff\x8b&\xf0\xef\x88\xcf^"\xf6\xa4\x1b \x02 \x0c\x18\xab?\x93\xd5\x88Cx\xf6\x0c\x1b\xcf\xd9\xd9\xd2\xd4"\xcf\x94\xede_>\x8c\x01~J\xea\x0ezB' ", "SigningAlgorithm": "ECDSA_SHA_256", "ResponseMetadata": {"HTTPStatusCode": 200, "HTTPHeaders": {"content-type": "application/x-amz-json-1.1", "content-length": "233",“连接”:“关闭”,“访问控制允许来源”:“*”,“访问控制允许方法”:“HEAD,GET,PUT,POST,DELETE,OPTIONS,PATCH”,“访问-control-allow-headers": "授权、内容类型、内容长度、内容 md5、缓存控制、x-amz-content-sha256、x-amz-date、x-amz-security-token、x -amz-user-agent、x-amz-target、x-amz-acl、x-amz-version-id、x-localstack-target、x-amz-tagging"、"访问控制公开标头": “x-amz-version-id”、“日期”:“星期六,2021 年 4 月 3 日 19:40:27 GMT”、“服务器”:“hypercorn-h11”}、“RetryAttempts”:0}}补丁”,“访问控制允许标题”:“授权,内容类型,内容长度,内容md5,缓存控制,x-amz-content-sha256,x-amz-date,x-amz-安全令牌、x-amz-user-agent、x-amz-target、x-amz-acl、x-amz-version-id、x-localstack-target、x-amz-tagging"、"访问控制-暴露头”:“x-amz-version-id”,“日期”:“星期六,2021 年 4 月 3 日 19:40:27 GMT”,“服务器”:“hypercorn-h11”},“重试尝试”:0} }补丁”,“访问控制允许标题”:“授权,内容类型,内容长度,内容md5,缓存控制,x-amz-content-sha256,x-amz-date,x-amz-安全令牌、x-amz-user-agent、x-amz-target、x-amz-acl、x-amz-version-id、x-localstack-target、x-amz-tagging"、"访问控制-暴露头”:“x-amz-version-id”,“日期”:“星期六,2021 年 4 月 3 日 19:40:27 GMT”,“服务器”:“hypercorn-h11”},“重试尝试”:0} }“星期六,2021 年 4 月 3 日 19:40:27 GMT”,“服务器”:“hypercorn-h11”},“重试次数”:0}}“星期六,2021 年 4 月 3 日 19:40:27 GMT”,“服务器”:“hypercorn-h11”},“重试次数”:0}}
验证错误:
“stacktrace”:“调用验证操作时发生错误(InvalidKeyUsageException):asn1:结构错误:标签不匹配(16 vs {class:1标签:13长度:69 isCompound:false}){可选:false显式:false application:false private:false defaultValue: tag: stringType:0 timeType:0 set:false omitEmpty:false} ecdsaSignature @2"
def _verify_signature(self, key_id, message, signature):
response = kms_client.verify(
KeyId=key_id,
Message=message,
MessageType="RAW",
Signature=signature,
SigningAlgorithm="ECDSA_SHA_256",
)
logger.log(msg=response, level=cl.log_level)
return response
client.verify 要求签名为字节https://boto3.amazonaws.com/v1/documentation/api/1.11.4/reference/services/kms.html#KMS.Client.verify
如果我离开,.encode()
我会得到同样的结果:
“stacktrace”:“调用验证操作时发生错误(InvalidKeyUsageException):asn1:结构错误:标签不匹配(16 vs {class:1标签:13长度:69 isCompound:false}){可选:false显式:false application:false private:false defaultValue: tag: stringType:0 timeType:0 set:false omitEmpty:false} ecdsaSignature @2"
def _sign_token(self, key_id, message):
signature = kms_client.sign(
KeyId=key_id,
Message=message,
MessageType="RAW",
SigningAlgorithm="ECDSA_SHA_256",
)
logger.log(msg=signature, level=cl.log_level)
return base64.b64encode(signature["Signature"])
笔记:
如果我在没有 base64 编码的情况下将 client.sign 响应“签名”传递给 client.verify,则验证通过。