当前位置: 首页 > 知识库问答 >
问题:

将AWS KMS非对称密钥签名/验证签名编码到Base64并验证

洪和风
2023-03-14

我使用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"
}

每当我尝试使用Python3中的API响应对“签名”进行base64编码base64.urlsafe\u b64encode(string)时,我都无法验证签名。以下是我收到的错误示例:

调用Verify操作时发生错误(InvalidKeyUsageExc0019): asn1:结构错误:标签不匹配(16 vs{class: 1标签: 2长度: 39 isCompound: true}){可选:假显式:假应用程序:假私有:假默认值:标签: stringType: 0 timeType: 0 set: false omitempty: false}ecdsaSignature@2

如何对从应用编程接口返回的“签名”字节串进行Bas64编码,并且仍然能够验证?

更新:

如果我更新为base64.b4encode而不是base64.urlsafe\u 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:27593”,“levelname”:“INFO”,“name”:“util.sign”,“lineno”:214,“message”:null,“env”:“local”,“KeyId”:“arn:aws:kms:us-east-1:00000000000000:key/309d8dc5-409e-4f57-96a8-c71223c84dc2”,“签名”:“b'0E\x02!\x00\xcc\x82\xf4$?\x9e\n\xd7$\x94\x9f.\x15\x5w\x19

验证错误:

“stacktrace”:“调用验证操作时发生错误(InvalidKeyUsageException):asn1:结构错误:标记不匹配(16 vs{class:1标记:13长度:69 isCompound:false}){可选:false显式:false应用程序:false私有:false默认值:标记:stringType:0时间类型:0集合:false省略空: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应用程序:false私有:false默认值:标记:stringType:0时间类型:0集合:false省略空: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"])

注:

如果我将client.sign响应“Signature”传递给client.verify而不使用base64编码,则验证通过。

共有2个答案

南门新荣
2023-03-14

AWS的支持过程奏效了。当我尝试验证而不是base64.b64decode()

贺桐
2023-03-14

AWS cli编码的字符串不是urlsafe-base64编码的!它使用标准base64编码,即base64.b64encode

标准的bas64编码使用三个元字符/=< /code>。/在路径或查询字符串中使用都不安全,并且URL安全编码分别用_< /code>和-替换这两个。由于/出现在AWS CLI编码的字符串中,因此可以推断出它使用标准的bas64编码,而不是URL安全编码。

base64.b64encode的返回值是bytes对象。通常使用Base-64编码将二进制编码为文本。要以文本形式获取值,您需要解码它(例如,将UTF-8解码为unicode字符串):

base64_encoded_as_str = base64.b64encode(binary_value).decode()

 类似资料:
  • 我试图使用javascript创建ECDSA算法的密钥对,签名消息,然后在服务器端验证它(使用Java)。 示例javascript代码: 例如: 我做错了什么?

  • 另外,这里还有一个函数演示,它从mod和指数生成PEM(摘自http://stackoverflow.com/questions/18835132/xml-to-pem-in-node-js) 前面提到的jsonwebtoken库可以使用任何一种方法来验证JWT--但是为什么呢?如果这两种验证方法都可以验证一个JWT签名,为什么它们都存在呢?他们之间有什么权衡?一个比另一个更安全吗?我应该使用哪一

  • 我想在客户端设备上使用通过Ed25519生成的私钥对JWS(json web签名)进行签名。然后将这个签名发送到我的后端,并用公钥验证它。为了熟悉这个过程,我想尝试在node js中对JWS进行签名和验证 我的私钥和公钥都已生成,可以在base58中使用。这是我目前使用Ed25519私钥签署JWT的尝试: 密钥必须是KeyObject或CryptoKey类型之一。收到一个Uint8Array的实例

  • 问题内容: 我有一个外部服务,在定义的事件发生后会给我回电,并用其私钥签署他的请求。 我已经存储了如下公钥: 因此,我的工作是通过验证签名来检查请求的内容是否未更改。 这是我的算法: 但是目前,我的算法已停止在此消息的“ PublicKey publicKey = keyFactory.generatePublic(publicKeySpec)”步骤处: 那么,如何以java api接受的方式加载

  • 我的理解是公钥加密,私钥解密...有谁能帮我弄明白吗?

  • 我在nodejs中有一个非常小的代码,我在其中签名一个字符串,然后尝试使用openssl生成的节点密码和密钥对来验证它。无论我尝试什么,结果总是“错误”,签名无法验证。 生成公钥/私钥对: 生成的密钥是(我不在乎是否公开): 然后,这是我的节点代码: 我尝试使用不同的算法和编码。我已经读了带有"fs"的PEM文件,也没有运气。我错过了什么?顺便说一句,这些键使用npm URSA模块完美工作,所以我