本文以ALIYUN CLI使用为例,简单描述了使用非对称CMK生成数字签名以及验证签名的场景。您也可以通过KMS的SDK来实现。

非对称加密场景,通常包含以下步骤:
  1. 签名者将验签公钥分发给消息接收者。
  2. 签名者使用签名私钥,对数据产生签名。
  3. 签名者将数据以及签名传递给消息接收者。
  4. 消息接收者获得数据和签名后,使用公钥针对数据验证签名的合法性。

开始之前

您需要使用ALIYUN CLI调用CreateKey接口,在KMS中创建恰当类型的非对称密钥(设定KeySpec参数),并且设定Usage参数为SIGN/VERIFY

  • 创建RSA签名密钥:

    aliyun kms CreateKey --KeySpec=RSA_2048 --KeyUsage=SIGN/VERIFY --ProtectionLevel=HSM
  • 创建NIST P-256签名密钥:

    aliyun kms CreateKey --KeySpec=EC_P256 --KeyUsage=SIGN/VERIFY --ProtectionLevel=HSM
  • 创建secp256k1签名密钥:

    aliyun kms CreateKey --KeySpec=EC_P256K --KeyUsage=SIGN/VERIFY --ProtectionLevel=HSM

签名预处理:计算消息摘要

无论是RSA还是ECC的签名运算,都是针对需要签名的消息首先计算摘要,随后对摘要进行签名运算。

说明 获取摘要的算法和调用KMS计算签名的算法需要一致。例如:签名算法ECDSA_SHA_256需要结合SHA-256摘要算法使用,如果使用SHA-384算法计算摘要,则和ECDSA_SHA_256算法不匹配。

示例中均使用SHA-256摘要算法。

1. 把需要签名的消息“this is message”存入文件message-file.txt:

echo "this is message" > message-file.txt

2. 计算消息的SHA-256摘要,二进制摘要存入文件message-sha256.bin:

openssl dgst -sha256 -binary -out message-sha256.bin  message-file.txt

调用KMS计算签名

您需要调用KMS接口使用私钥计算消息的签名。

1. 在对消息摘要进行网络传输之前,首先需要对其进行Base64编码:

openssl base64 -in message-sha256.bin

得到Base64编码后的摘要如下:

uCx5YpLfBrqoYMP8Hf9H7j9/1zT+PPxq1qJRW6uQbos=

2. 随后可以将Base64编码后的摘要传入KMS,产生签名。

说明 这一步针对不同的密钥和签名算法,调用KMS时传入的参数以及生成的结果均不相同。示例中产生的每种签名结果,被分别存入了不同的文件中。
  • RSASSA-PSS

    RSA密钥可以使用RSASSA-PSS算法结合SHA-256摘要进行签名,执行以下ALIYUN CLI命令:

    aliyun kms AsymmetricSign --KeyId=**** --KeyVersionId=**** \
        --Algorithm=RSA_PSS_SHA_256 --Digest=hRP2cu...
    {
            "KeyId": "****",
            "KeyVersionId": "****",
            "Value": "J7xmdnZ...",
            "RequestId": "70f78da9-c1b6-4119-9635-0ce4427cd424"
    }

    对签名结果Value进行Base64解码并输出二进制签名到文件rsa_pss_signature.bin:

    echo J7xmdnZ... | openssl base64 -d -out rsa_pss_signature.bin
  • RSASSA_PKCS1_V1_5

    RSA密钥可以使用RSASSA_PKCS1_V1_5算法结合SHA-256摘要进行签名,执行以下ALIYUN CLI命令:

    aliyun kms AsymmetricSign --KeyId=**** --KeyVersionId=**** \
        --Algorithm=RSA_PKCS1_SHA_256 --Digest=hRP2cu...
    {
            "KeyId": "****",
            "KeyVersionId": "****",
            "Value": "qreBkH/u...",
            "RequestId": "4be57288-f477-4ecd-b7be-ad8688390fbc"
    }

    对签名结果Value进行Base64解码并输出二进制签名到文件rsa_pkcs1_signature.bin:

    echo qreBkH/u... | openssl base64 -d -out rsa_pkcs1_signature.bin
  • NIST P-256

    NIST曲线P-256可以使用ECDSA算法结合SHA-256摘要进行签名,执行以下ALIYUN CLI命令:

    aliyun kms AsymmetricSign --KeyId=**** --KeyVersionId=**** \
        --Algorithm=ECDSA_SHA_256 --Digest=hRP2cu...
    {
            "KeyId": "****",
            "KeyVersionId": "****",
            "Value": "MEYCIQD33Y98...",
            "RequestId": "472d789c-d4be-4271-96bb-367f7f0f8ec3"
    }

    对签名结果Value进行Base64解码并输出二进制签名到文件ec_p256_signature.bin:

    echo MEYCIQD33Y98... | openssl base64 -d -out ec_p256_signature.bin
  • secp256k1

    执行以下ALIYUN CLI命令:

    aliyun kms AsymmetricSign --KeyId=**** --KeyVersionId=**** \
        --Algorithm=ECDSA_SHA_256 --Digest=hRP2cu...
    {
            "KeyId": "****",
            "KeyVersionId": "****",
            "Value": "MEYCIQDWuuI...",
            "RequestId": "fe41abed-91e7-4069-9f6b-0048f5bf4de5"
    }

    对签名结果Value进行Base64解码并输出二进制签名到文件ec_p256k_signature.bin:

    echo MEYCIQDWuuI... | openssl base64 -d -out ec_p256k_signature.bin

获取公钥

从KMS得到相应的非对称密钥的公钥。具体操作,请参见获取公钥。对应于上述示例,我们做如下假定:

  • 将RSA密钥的公钥存入:rsa_publickey.pub
  • 将NIST P-256密钥的公钥存入:ec_p256_publickey.pub
  • 将secp256k1密钥的公钥存入:ec_p256k_publickey.pub

使用公钥验证签名

根据不同的密钥使用不同类型算法,分别使用如下的命令行进行签名的验证:

  • RSASSA-PSS
    openssl dgst \
        -verify rsa_publickey.pub \
        -sha256 \
        -sigopt rsa_padding_mode:pss \
        -sigopt rsa_pss_saltlen:-1 \
        -signature rsa_pss_signature.bin \
        message-file.txt
  • RSASSA_PKCS1_V1_5
    openssl dgst \
        -verify rsa_publickey.pub \
        -sha256 \
        -signature rsa_pkcs1_signature.bin \
        message-file.txt
  • NIST P-256
    openssl dgst \
        -verify ec_p256_publickey.pub \
        -sha256 \
        -signature ec_p256_signature.bin \
        message-file.txt
  • secp256k1
    openssl dgst \
        -verify ec_p256k_publickey.pub \
        -sha256 \
        -signature ec_p256k_signature.bin \
        message-file.txt

如果验证成功,您应当看到如下输出:

Verified OK