PKCS#11 API-강좌4
PKCS#11 API-강좌4
RSA Key Generation and Encryption/Decryption 과 Sign/Verify 예제
강좌3 에서는 AES Key를 사용하는 예제를 보여 주었습니다. 강좌4 에서는 Asymmetric Key인 RSA 2048 bit Key를 생성하여, 테스트 데이타로 생성된 64-byte data를 Encryption/Decryption 하고, SHA256으로 Hash 하여 32-byte Digest를 만들고, 이 Digest를 Sign/Verify 하는 기능을 수행하는 예제입니다. 또 이번 예제에서는 생성되어, HSM에 저장된 Key를 삭제하는 C_DistroyObject() 함수도 사용하였습니다.
Asymmetric Key이기 때문에 Private Key 와 Public Key 두 개가 생성됩니다. Key Label은 RSA5Key 를 사용하였습니다. Encryption/Decryption 암호 연산과 Sign/Verify 연산 모두 HSM 장비안에서 수행됩니다.
강좌3 에서 제시한 소스와 유사하므로, 다른 부분만 기술하였습니다.
// *** HEADER FILES ***
. . . . . . . .
static CK_OBJECT_CLASS PublicKeyClass = CKO_PUBLIC_KEY;
static CK_OBJECT_CLASS PrivateKeyClass = CKO_PRIVATE_KEY;
static CK_KEY_TYPE RSAKeyType = CKK_RSA;
// *** MAIN ***************************************************************************************
int main(int argc, char* argv[])
{
………….
//4. Generate RSA Key and Encryption/Decryption & Sign/Verify test
rc = PKCS11_SampleCode::RSASamples(hSession);
if ( rc != CKR_OK ) throw buffer ;
………..
}
// *** end of MAIN ********************************************************************************
// *** RSA SAMPLE CODE ****************************************************************************
CK_RV PKCS11_SampleCode::RSASamples(CK_SESSION_HANDLE hSession)
{
printf("\n\n~~~ RSA Key Generation, Encryption/Decryption, Signing/Verify ~~~~~~~~~~~~~~~~~~~~~~~~\n");
// NOTES:
// Key Generation: Mechanism CKM_RSA_PKCS_KEY_PAIR_GEN is supported to generate keys
// A 2048 bit key pair is generated in this example.
// Encrypt/Decrypt: Mechanisms CKM_RSA_PKCS is used in this example
//
// Digest: Mechanisms CKM_SHA_256 is used in this example
//
// Sign/Verify: Mechanisms CKM_RSA_PKCS is used in this example.
//
CK_RV rc;
try
{
// generate some data
CK_BYTE data[64];
CK_ULONG dataLen = sizeof(data);
int i;
rc = pkcs11.GenerateRandom(hSession, data, dataLen);
printf("\r\nOriginal Data : ") ;
for ( i = 0 ; i < 64 ; i++ ) {
printf(" %02X ",data[i]) ;
}
// generate a key pair
CK_OBJECT_HANDLE hPubKey;
CK_OBJECT_HANDLE hPrivKey;
CK_ULONG ModulusBits = 2048 ; // for RSA 2048
CK_CHAR label[] = "RSA5Key";
rc = PKCS11_SampleCode::generateRSAKeyPair(hSession, hPubKey, hPrivKey, ModulusBits,label);
if ( rc != CKR_OK ) return rc ;
// encrypt/decrypt
rc = PKCS11_SampleCode::RSAEncryptDecrypt(hSession, hPubKey, hPrivKey, data, dataLen);
if ( rc != CKR_OK )
{
// tidy up
pkcs11.DestroyObject(hSession, hPubKey);
pkcs11.DestroyObject(hSession, hPrivKey);
return rc ;
}
// digest
CK_BYTE hash[32] = {0};
CK_ULONG hashLen = sizeof(hash);
rc = PKCS11_SampleCode::sha256Hash(hSession, data, dataLen, hash, &hashLen);
// sign/verify
rc = PKCS11_SampleCode::RSASignVerify(hSession, hPubKey, hPrivKey, hash, hashLen);
// tidy up
pkcs11.DestroyObject(hSession, hPubKey);
pkcs11.DestroyObject(hSession, hPrivKey);
}
catch (char* e)
{
printf(e);
}
catch (...){}
return rc;
}
// ___ GENERATE AN RSA KEY PAIR _______________________________________________
CK_RV PKCS11_SampleCode::generateRSAKeyPair(CK_SESSION_HANDLE hSession, CK_OBJECT_HANDLE& hPubKey, CK_OBJECT_HANDLE& hPrivKey, CK_ULONG ModulusBits, CK_CHAR_PTR label)
{
printf("\n\n--- Generate RSA Key Pair --------------\n");
CK_RV rc;
try
{
// get an RSA Key Generation mechanism
CK_MECHANISM genMech = {CKM_RSA_PKCS_KEY_PAIR_GEN, NULL_PTR, 0};
// declare a Public Exponent
CK_BYTE PublicExponent[] = {0,0,0,0x03};
// generate the RSA Public Template
CK_ATTRIBUTE pubKeyTemplate[] =
{
{CKA_CLASS, &PublicKeyClass, sizeof(PublicKeyClass)},
{CKA_TOKEN, &bTrue, sizeof(bTrue)},
{CKA_PRIVATE, &bTrue, sizeof(bTrue)},
{CKA_MODIFIABLE, &bFalse, sizeof(bFalse)},
{CKA_ENCRYPT, &bTrue, sizeof(bTrue)},
{CKA_VERIFY, &bTrue, sizeof(bTrue)},
{CKA_WRAP, &bTrue, sizeof(bTrue)},
{CKA_KEY_TYPE, &RSAKeyType, sizeof(RSAKeyType)},
{CKA_MODULUS_BITS, &ModulusBits, sizeof(ModulusBits)},
{CKA_PUBLIC_EXPONENT, &PublicExponent, sizeof(PublicExponent)}
};
// generate the RSA Private Template
CK_ATTRIBUTE privKeyTemplate[] =
{
{CKA_CLASS, &PrivateKeyClass, sizeof(PrivateKeyClass)},
{CKA_TOKEN, &bTrue, sizeof(bTrue)},
{CKA_PRIVATE, &bTrue, sizeof(bTrue)},
{CKA_LABEL, label, strlen((char*)label)},
{CKA_MODIFIABLE, &bFalse, sizeof(bFalse)},
{CKA_KEY_TYPE, &RSAKeyType, sizeof(RSAKeyType)},
{CKA_DECRYPT, &bTrue, sizeof(bTrue)},
{CKA_SIGN, &bTrue, sizeof(bTrue)},
{CKA_UNWRAP, &bTrue, sizeof(bTrue)},
{CKA_SENSITIVE, &bTrue, sizeof(bTrue)},
{CKA_EXTRACTABLE, &bFalse, sizeof(bFalse)}
};
// reset the RSA Key handles
hPubKey = 0;
hPrivKey = 0;
// generate the RSA Key Pair
rc = pkcs11.GenerateKeyPair( hSession, &genMech,
pubKeyTemplate, sizeof(pubKeyTemplate)/sizeof(CK_ATTRIBUTE),
privKeyTemplate, sizeof(privKeyTemplate)/sizeof(CK_ATTRIBUTE),
&hPubKey, &hPrivKey );
}
catch (char* e)
{
printf(e);
}
catch (...){}
return rc;
}
// ___ RSA ENCRYPT/DECRYPT ____________________________________________________
CK_RV PKCS11_SampleCode::RSAEncryptDecrypt(CK_SESSION_HANDLE hSession, CK_OBJECT_HANDLE hPubKey,CK_OBJECT_HANDLE hPriKey, const CK_BYTE_PTR data, const CK_ULONG dataLen)
{
printf("\n\n--- RSA Encrypt/Decrypt ----------------\n");
CK_RV rc;
try
{
// declare variables
CK_ULONG realDataLen = 256 ; // Max Size for 2048 bit key
CK_BYTE_PTR encData = new CK_BYTE[realDataLen];
CK_BYTE_PTR decData = new CK_BYTE[realDataLen];
CK_ULONG encLen = realDataLen;
CK_ULONG decLen = realDataLen;
CK_ULONG i ;
// set up the RSA encrypt/decrypt mechanism (dependent upon the bit length)
CK_MECHANISM encDecMech = { CKM_RSA_PKCS, NULL_PTR, 0 } ;
// encrypt the data
rc = pkcs11.EncryptInit(hSession, &encDecMech, hPubKey);
rc = pkcs11.Encrypt(hSession, data, dataLen, encData, &encLen);
printf("\r\nEncrypted Data : ") ;
for ( i = 0 ; i < encLen ; i++ ) {
printf(" %02X ",encData[i]) ;
}
printf("\r\n") ;
// decrypt the data
rc = pkcs11.DecryptInit(hSession, &encDecMech, hPriKey);
rc = pkcs11.Decrypt(hSession, encData, encLen, decData, &decLen);
printf("\r\nDecrypted Data : ") ;
for ( i = 0 ; i < decLen ; i++ ) {
printf(" %02X ",decData[i]) ;
}
printf("\r\n") ;
// tidy up
delete [] encData;
delete [] decData;
}
catch (char* e)
{
printf(e);
}
catch (...) {}
return rc;
}
// *** SHA256 HASH **********************************************************************************
CK_RV PKCS11_SampleCode::sha256Hash(CK_SESSION_HANDLE hSession, CK_BYTE* data, CK_ULONG dataLen, CK_BYTE* hash, CK_ULONG* hashLen)
{
printf("\n\n--- SHA256 Hash --------------------------\n");
CK_RV rc;
try
{
CK_ULONG hLength , i ;
// declare the hashing mechanism
CK_MECHANISM hashMech = {CKM_SHA256, NULL_PTR, 0};
// perform a digest
rc = pkcs11.DigestInit(hSession, &hashMech);
rc = pkcs11.Digest(hSession, data, dataLen, hash, hashLen);
hLength = *hashLen ;
printf("\r\nHashed Data : %d bytes \r\n", hLength ) ;
for ( i = 0 ; i < hLength ; i++ ) {
printf(" %02X ",hash[i]) ;
}
printf("\r\n") ;
}
catch (char* e)
{
printf(e);
}
catch (...) {}
return rc;
}
// ___ RSA SIGN/VERIFY ________________________________________________________
CK_RV PKCS11_SampleCode::RSASignVerify(CK_SESSION_HANDLE hSession, CK_OBJECT_HANDLE hPubKey, CK_OBJECT_HANDLE hPrivKey, const CK_BYTE_PTR data, const CK_ULONG dataLen)
{
printf("\n\n--- RSA Sign/Verify --------------------\n");
CK_RV rc;
try
{
// declare a signature buffer
unsigned char signature[512];
CK_ULONG signatureLen = sizeof(signature);
CK_ULONG i ;
// get an RSA sign/verify mechanism
CK_MECHANISM signVerifyMech = { CKM_RSA_PKCS, NULL_PTR, 0 };
// sign the data
rc = pkcs11.SignInit(hSession, &signVerifyMech, hPrivKey);
rc = pkcs11.Sign(hSession, data, dataLen, signature, &signatureLen);
printf("\r\nSigned Data : %d bytes \r\n",signatureLen ) ;
for ( i = 0 ; i < signatureLen ; i++ ) {
printf(" %02X ",signature[i]) ;
}
printf("\r\n") ;
// verify the signature
rc = pkcs11.VerifyInit(hSession, &signVerifyMech, hPubKey);
rc = pkcs11.Verify(hSession, data, dataLen, signature, signatureLen);
if ( rc == CKR_OK ) printf("\r\n--Verification is OK----\r\n");
else printf("\r\n--Verification is Fail ----\r\n");
}
catch (char* e)
{
printf(e);
}
catch(...) {}
return rc;
}
예제 프로그램 수행 결과 값
위 프로그램을 수행한 결과 값은 아래와 같이 나옵니다. 2048 Bit RSA Key를 사용하였기 때문에, Encryption 및 Signing 결과 값이 256 byte 입니다. 참고로 CKM_RSA_PKCS Mechanism을 사용할 시, Input Data의 최대 크기는 245(256 – 11) byte 가 되며, Output Data는 256 Byte 가 됩니다. 256 Byte인 이유는 2048 Bit 이기 때문입니다(RSA Encryption에서 결과치는 Key Length와 동일하고, Input Data 최대치는 Key Length – 11 byte 입니다)
~~~ RSA Key Generation, Encryption/Decryption, Signing/Verify ~~~~~~~~~~~~~~~~~~~~~~~~
Original Data : EB 79 BC 3D 3E 24 66 F5 C9 06 75 F4 49 E6 36 6D 48 7C 67 D7 52 B4 01 90 64 2F 79 CF 60 9C 41 A6 1B 7F 01 54 58 E9 90 01 D1 B3 BF 60 53 1B E6 FC 7F B3 87 09 80 79 A7 C8 83 C4 78 6A 8D 95 06 05
--- Generate RSA Key Pair --------------
--- RSA Encrypt/Decrypt ----------------
Encrypted Data : 0C 79 9B EE AB 32 10 A2 82 E3 83 00 E9 C3 9A DA 9D F3 13 35 24 92 80 EF 4A 0E 43 66 CB 3C 5E A2 30 24 8B 5A F7 F4 A2 0B C6 1C BB A2 50 4C 5E DB 34 C4 58 2A 0F 6E B0 9D 65 59 35 82 38 83 93 FC 5F B9 FC FC 2C DE F1 3C 3C 96 55 79 C4 21 C8 4D A2 A1 C6 2A 5D 84 84 F3 60 E1 3F 3C 61 45 6D 37 A0 C5 65 B0 A4 FD 3F AF 7A 77 66 3B 0D 4B 9F 1D 1E 55 5F 4E DC 29 1C 57 6F B4 22 A8 C9 09 BB FC B4 34 8C 22 5C 16 4F 72 9C E4 75 6E 5D 68 68 30 19 27 30 1C DD A9 D1 BF 81 61 26 CD D9 2A 54 C4 A5 1A 5D 47 D7 9C 2D DB EE 4C D4 7A D1 CF 3E E4 F3 43 9F 6E 62 84 95 E1 33 E7 44 46 57 DB A8 53 DD 31 D7 68 AB 71 A5 26 F0 26 65 F7 7A 72 5F B3 1A 0D F1 92 2C 1B 22 06 EE 97 76 82 17 4C 51 5E 1B 3D 7C 8B 97 4F 5B 0F 29 F4 E9 0E 6C D7 DD 2C AD 6E 94 A3 B2 B8 A2 2E 52 16 34 9C 1E 02 F6 A9
Decrypted Data : EB 79 BC 3D 3E 24 66 F5 C9 06 75 F4 49 E6 36 6D 48 7C 67 D7 52 B4 01 90 64 2F 79 CF 60 9C 41 A6 1B 7F 01 54 58 E9 90 01 D1 B3 BF 60 53 1B E6 FC 7F B3 87 09 80 79 A7 C8 83 C4 78 6A 8D 95 06 05
--- SHA256 Hash --------------------------
Hashed Data : 32 bytes
3D 20 CB 8F E2 93 A9 D3 6C 84 03 D2 8D 3A C9 14 45 36 D5 F1 58 F7 82 8E F8 B6 93 1A B1 AF F1 37
--- RSA Sign/Verify --------------------
Signed Data : 256 bytes
48 6D 75 AE 50 BF 70 A5 F3 92 0C 03 AE A4 FD DC 3F D7 20 C7 E9 88 ED 09 25 F4 D9 AB 3E 44 4A 02 1A E6 53 49 78 8D 6E 29 15 64 7E 39 94 DE 30 E8 00 0E 27 7B 19 60 02 C6 54 43 A0 61 F8 19 2A A0 C6 E8 19 BD B9 47 F4 0C 68 E1 44 70 25 BE 31 B6 C6 3A 23 01 F3 13 63 D5 E4 CE 07 CA 35 E7 ED 7A 14 3E 53 E0 D7 4A 36 C0 C6 AE 50 8B AE CE 4D C8 8D 76 4B 72 B7 D5 AD B2 CC 1C D4 81 66 3E ED 06 B0 E3 D2 83 DA C5 28 CB CE F9 4C 7A 23 F7 EE 52 62 61 F3 AE FF C9 FE 58 C3 87 A8 EB 7A 5C DA C1 90 3B 49 A2 5E DA 47 B6 A8 19 08 82 92 C7 29 4C CF 5A DE AB D5 B2 21 52 47 95 B0 43 AD 33 E3 F3 AB D5 44 DB 25 03 4B D8 9C 82 0F A4 C0 E7 81 7B C3 7D 93 EA AA FE 91 2F DC F0 3C C9 07 CF BA CF D4 19 77 9B 77 CF BF B5 EA 69 A0 ED 16 F4 BC 94 86 F9 7D 36 06 46 20 D0 FB 28 4C 2E 30 FA 5E 71
--Verification is OK----
Last updated