Tip / Sign in to post questions, reply, level up, and achieve exciting badges. Know more

Signature verification primitives of HSM Performance Library – KBA234711

Signature verification primitives of HSM Performance Library – KBA234711

IFX_Publisher1
Community Manager
Community Manager
Community Manager
250 sign-ins First comment on KBA 250 replies posted

Signature verification primitives of HSM Performance Library – KBA234711

Community Translation: HSMパフォーマンスライブラリの署名検証プリミティブ – KBA234711

Version: **

The Hardware Security Module (HSM) Performance Library comprises three drivers:

  • HsmCrpt
  • HsmIpc
  • HsmProt

In this article, we explain how to practically make use of 3 signature verification primitives supported by HsmCrpt driver.

RSA signature verification primitive

RSA signature verification can be used to validate the signature of a message and hence decide if the message is authentic or not. The signature of a message is the hash of the message encrypted by an RSA Private Key. This signature can be decrypted using an associated RSA Public Key to retrieve the hash. This hash can then be compared with the hash of the message computed again. If the two-hash values match, then the message can be considered valid or authentic.

The steps described below can be used for signature verification based on RSASSA-PKCS1-v1_5 using the function “HsmCrpt_RsaExp65537”.

  1. Define a plain text. Let us call it “plainTxt”. We shall be validating if this “plainTxt” is authentic or not.
  2. Use a 128-byte RSA Public Key modulus. Ensure that the modulus is stored as an array in Little Endian Format. Let us call it “modulus”.
  3. Compute the SHA2-256 of the plain text (e.g. using openssl commands) and encrypt the hash with a 128-byte RSA private exponent. This 128-byte encrypted hash is called a signature. This is also stored as an array in Little Endian Format. Let us call the array “encryptedSignature”.
  4. Using the HsmCrpt function “HsmCrpt_Sha2_256”, compute the Hash of “plainTxt”. HsmCrpt_Sha2_256(plainTxt,(sizeof(plainTxt))-1, Hash1,32)
    The computed hash will be a 32-byte value and let us call it “Hash1”. Note that (sizeof(plainTxt))-1 was used since “sizeof” function also considers the null character of the string.
  5. Use the function HsmCrpt_RsaExp65537 as shown below to retrieve the original message hash: HsmCrpt_RsaExp65537(modulus,sizeof(modulus),encryptedSignature,sizeof(encryptedSignature),Hash2);
    The output Hash2 of the above function shall be 128 bytes long (since the modulus used is 128 bytes long).
  6. The RSA output is returned in the Big-Endian format. Also, note that only the first 32 bytes of “Hash 2” is significant. So, do an endian conversion for the first 32 bytes of Hash2. If this data matches with “Hash1”, then the message can be considered authentic.

ECDSA signature verification primitive

HsmCrpt supports a primitive that performs ECDSA verification operation according to FIPS PUB 186-4. It supports NIST curves NIST P-256 and NIST P-384 only.

Input test vectors for ECDSA according to FIPS 186-4 is available in https://csrc.nist.gov/projects/cryptographic-algorithm-validation-program/digital-signatures

In this example, we will use the same vectors available in line no 1322 of the file SigVer.rsp to verify the signature.

  1. The message is “73c5f6a67456ae48209b5f8……”. This can be stored in an array as
    uint8 message_verify[]= {0x73U, 0xC5U, 0xF6U,…….};
  1. R is “1d75830cd36f4c9aa181b2c4221e87f176b7f05b7c87824e82e396c88315c407”. This can be stored in an array as:
    uint8 XPtr[]= {0x07U, 0xC4U, 0x15U, 0x83U, 0xC8U, 0x96U, 0xE3U, 0x82U, 0x4EU, 0x82U, 0x87U, 0x7CU, 0x5BU, 0xF0U, 0xB7U, 0x76U, 0xF1U, 0x87U, 0x1EU, 0x22U, 0xC4U, 0xB2U, 0x81U, 0xA1U, 0x9AU, 0x4CU, 0x6FU, 0xD3U, 0x0CU, 0x83U, 0x75U, 0x1DU};
  1. S is “cb2acb01dac96efc53a32d4a0d85d0c2e48955214783ecf50a4f0414a319c05a“. This can be stored in an array as:
    uint8 YPtr[]={0x5AU, 0xC0U, 0x19U, 0xA3U, 0x14U, 0x04U, 0x4FU, 0x0AU, 0xF5U, 0xECU, 0x83U, 0x47U, 0x21U, 0x55U, 0x89U, 0xE4U, 0xC2U, 0xD0U, 0x85U, 0x0DU, 0x4AU, 0x2DU, 0xA3U, 0x53U, 0xFCU, 0x6EU, 0xC9U, 0xDAU, 0x01U, 0xCBU, 0x2AU, 0xCBU};
  1. Public key X field can be stored as:
    uint8 PubKey_XPtr[]={0x64U, 0x28U, 0x3DU, 0xAAU, 0xEEU, 0xE3U, 0x35U, 0xF3U, 0x52U, 0xBFU, 0x43U, 0xE7U, 0x28U, 0x33U, 0x9FU, 0xA4U, 0xF9U, 0x57U, 0x3AU, 0x4EU, 0xE5U, 0x3EU, 0x67U, 0x75U, 0x74U, 0xC5U, 0xE1U, 0x50U, 0x6FU, 0x6AU, 0xFCU, 0xE0U};
  1. Public key Y field can be stored as:
    uint8 PubKey_YPtr[]={0x2AU, 0xF2U, 0x12U, 0x3FU, 0x37U, 0x4BU, 0x5DU, 0x3FU, 0xE6U, 0xDDU, 0x16U, 0x08U, 0x87U, 0x32U, 0x54U, 0xE2U, 0x16U, 0xF3U, 0xFAU, 0x99U, 0x4DU, 0x19U, 0xD9U, 0x07U, 0x36U, 0x46U, 0x1EU, 0xC9U, 0x89U, 0xD6U, 0x59U, 0x7FU};
  1. Now declare two variables as shown below and assign them with the mentioned values:
    HsmCrpt_EccPointType ECDSA_SignaturePtr;
    HsmCrpt_EccPubKeyType ECDSA_PublicKeyPtr;
    ECDSA_SignaturePtr.XPtr=XPtr;
    ECDSA_SignaturePtr.YPtr=YPtr;
    ECDSA_PublicKeyPtr.CurveId = HSMCRPT_ECC_ECP_SECP256R1;
    ECDSA_PublicKeyPtr.PubKey.XPtr=PubKey_XPtr;
    ECDSA_PublicKeyPtr.PubKey.YPtr=PubKey_YPtr;
  1. Compute the SHA2-256 of message_verify and derive the “digest” using HsmCrpt_Sha2_256(message_verify, (sizeof(message_verify)), digest,32);
  2. Do an endian-swap of the computed digest. The new digest is “digest_swapped”.
  3. Now verify the signature using:
    HsmCrpt_EcdsaVer(&ECDSA_SignaturePtr,&ECDSA_PublicKeyPtr,digest_swapped,32,&VerResult);

Since the verification should be successful with the above test vectors, HSMCRPT_ECDSAVER_VERIFICATION_OK shall be returned to the variable “VerResult”.

Ed25519 signature verification primitive

HsmCrpt supports a primitive that performs Ed25519 signature verification using Curve25519 according to the RFC8032 standard. The message is not used as an input, but the digest calculated, for example, from the concatenation of the lower 32 bytes of signature, public key, and message using SHA-512 are used.

In this example, we will verify the functionality of this primitive using a test vector specified in RFC8032.

  1. Test vector used is "TEST 2" in RFC8032 - section 7.1
  2. Public key, signature, and message are stored as arrays based on “TEST 2”:
    const uint8 Ed25519_pk[32] = {0x3d,0x40,.....0x0c};
    const uint8 Ed25519_sign[64]  = {0x92,0xa0,0x09,.......,0x00};
    uint8 Ed25519_msg[1] = {0x72};
  1. Now compute the digest "Ed25519_msg_digest" based on the concatenation logic mentioned before. Here is an example:
    HsmCrpt_Sha2_512_Start();
    HsmCrpt_Sha2_512_Update(Ed25519_sign, 64>>1);
    HsmCrpt_Sha2_512_Update(Ed25519_pk, 32);
    HsmCrpt_Sha2_512_Update(Ed25519_msg,1);
    HsmCrpt_Sha2_512_Finish(Ed25519_msg_digest,64);
  1. Now, verify the signature using:
    HsmCrpt_Ed25519Verification(Ed25519_pk,Ed25519_msg_digest,Ed25519_sign,& VerResult);

Since the verification should be successful with the above test vectors, HSMCRPT_ED25519_VERIFICATION_OK shall be returned to the variable “VerResult”.

0 Likes
406 Views