144 lines
6.5 KiB
C++
144 lines
6.5 KiB
C++
// Copyright (c) Microsoft Corporation.
|
|
// Licensed under the MIT License.
|
|
|
|
/**
|
|
* @brief This sample demonstrates how to sign data with both a RSA key and an EC key using the
|
|
* synchronous methods of the CryptographyClient.
|
|
*
|
|
* @remark The following environment variables must be set before running the sample.
|
|
* - AZURE_KEYVAULT_URL: To the Key Vault account URL.
|
|
* - AZURE_TENANT_ID: Tenant ID for the Azure account.
|
|
* - AZURE_CLIENT_ID: The Client ID to authenticate the request.
|
|
* - AZURE_CLIENT_SECRET: The client secret.
|
|
*
|
|
*/
|
|
|
|
#include <azure/core.hpp>
|
|
#include <azure/identity.hpp>
|
|
#include <azure/keyvault/keys.hpp>
|
|
|
|
#include <chrono>
|
|
#include <iostream>
|
|
#include <vector>
|
|
|
|
using namespace Azure::Security::KeyVault::Keys;
|
|
using namespace Azure::Security::KeyVault::Keys::Cryptography;
|
|
using namespace std::chrono_literals;
|
|
|
|
int main()
|
|
{
|
|
|
|
auto tenantId = std::getenv("AZURE_TENANT_ID");
|
|
auto clientId = std::getenv("AZURE_CLIENT_ID");
|
|
auto clientSecret = std::getenv("AZURE_CLIENT_SECRET");
|
|
auto credential
|
|
= std::make_shared<Azure::Identity::ClientSecretCredential>(tenantId, clientId, clientSecret);
|
|
|
|
KeyClient keyClient(std::getenv("AZURE_KEYVAULT_URL"), credential);
|
|
|
|
auto rsaKeyName = "CloudRsaKey-" + Azure::Core::Uuid::CreateUuid().ToString();
|
|
auto keyOptions = CreateRsaKeyOptions(rsaKeyName, false);
|
|
keyOptions.KeySize = 2048;
|
|
|
|
auto ecKeyName = "CloudEcKey-" + Azure::Core::Uuid::CreateUuid().ToString();
|
|
auto ecKeyOptions = CreateEcKeyOptions(ecKeyName, false);
|
|
ecKeyOptions.CurveName = KeyCurveName::P256K;
|
|
|
|
auto returnValue = 0;
|
|
try
|
|
{
|
|
KeyVaultKey cloudRsaKey = keyClient.CreateRsaKey(keyOptions).Value;
|
|
std::cout << " - Key is returned with name " << cloudRsaKey.Name() << " and type "
|
|
<< cloudRsaKey.GetKeyType().ToString() << std::endl;
|
|
|
|
KeyVaultKey cloudEcKey = keyClient.CreateEcKey(ecKeyOptions).Value;
|
|
std::cout << " - Key is returned with name " << cloudEcKey.Name() << " and type "
|
|
<< cloudEcKey.GetKeyType().ToString() << std::endl;
|
|
|
|
CryptographyClient rsaCryptoClient(cloudRsaKey.Id(), credential);
|
|
|
|
CryptographyClient ecCryptoClient(cloudEcKey.Id(), credential);
|
|
|
|
uint8_t const dataSource[]
|
|
= "This is some sample data which we will use to demonstrate sign and verify";
|
|
std::vector<uint8_t> data(std::begin(dataSource), std::end(dataSource));
|
|
|
|
// digestRaw simulates some text data that has been hashed using the SHA256 algorithm
|
|
// and then base 64 encoded. It is not relevant for the sample how to create the SHA256
|
|
// hashed digest.
|
|
std::vector<uint8_t> digest
|
|
// cspell: disable-next-line
|
|
= Azure::Core::Convert::Base64Decode("RUE3Nzg4NTQ4QjQ5RjFFN0U2NzAyQzhDNEMwMkJDOTA=");
|
|
|
|
// Sign and Verify from digest
|
|
SignResult rsaSignResult = rsaCryptoClient.Sign(SignatureAlgorithm::RS256, digest).Value;
|
|
std::cout << " - Signed digest using the algorithm " << rsaSignResult.Algorithm.ToString()
|
|
<< ", with key " << rsaSignResult.KeyId << ". The resulting signature is: "
|
|
<< Azure::Core::Convert::Base64Encode(rsaSignResult.Signature) << std::endl;
|
|
|
|
SignResult ecSignResult = ecCryptoClient.Sign(SignatureAlgorithm::ES256K, digest).Value;
|
|
std::cout << " - Signed digest using the algorithm " << ecSignResult.Algorithm.ToString()
|
|
<< ", with key " << ecSignResult.KeyId << ". The resulting signature is: "
|
|
<< Azure::Core::Convert::Base64Encode(ecSignResult.Signature) << std::endl;
|
|
|
|
VerifyResult rsaVerifyResult
|
|
= rsaCryptoClient.Verify(SignatureAlgorithm::RS256, digest, rsaSignResult.Signature).Value;
|
|
std::cout << " - Verified the signature using the algorithm "
|
|
<< rsaVerifyResult.Algorithm.ToString() << ", with key " << rsaVerifyResult.KeyId
|
|
<< ". Signature is valid: " << (rsaVerifyResult.IsValid ? "True" : "False")
|
|
<< std::endl;
|
|
|
|
VerifyResult ecVerifyResult
|
|
= ecCryptoClient.Verify(SignatureAlgorithm::ES256K, digest, ecSignResult.Signature).Value;
|
|
std::cout << " - Verified the signature using the algorithm "
|
|
<< ecVerifyResult.Algorithm.ToString() << ", with key " << ecVerifyResult.KeyId
|
|
<< ". Signature is valid: " << (ecVerifyResult.IsValid ? "True" : "False")
|
|
<< std::endl;
|
|
|
|
// Sign and Verify from data
|
|
SignResult rsaSignDataResult = rsaCryptoClient.SignData(SignatureAlgorithm::RS256, data).Value;
|
|
std::cout << " - Signed data using the algorithm " << rsaSignDataResult.Algorithm.ToString()
|
|
<< ", with key " << rsaSignDataResult.KeyId << ". The resulting signature is: "
|
|
<< Azure::Core::Convert::Base64Encode(rsaSignDataResult.Signature) << std::endl;
|
|
|
|
SignResult ecSignDataResult = ecCryptoClient.SignData(SignatureAlgorithm::ES256K, data).Value;
|
|
std::cout << " - Signed data using the algorithm " << ecSignDataResult.Algorithm.ToString()
|
|
<< ", with key " << ecSignDataResult.KeyId << ". The resulting signature is: "
|
|
<< Azure::Core::Convert::Base64Encode(ecSignDataResult.Signature) << std::endl;
|
|
|
|
VerifyResult rsaVerifyDataResult
|
|
= rsaCryptoClient.VerifyData(SignatureAlgorithm::RS256, data, rsaSignDataResult.Signature)
|
|
.Value;
|
|
std::cout << " - Verified the signature using the algorithm "
|
|
<< rsaVerifyDataResult.Algorithm.ToString() << ", with key "
|
|
<< rsaVerifyDataResult.KeyId
|
|
<< ". Signature is valid: " << (rsaVerifyDataResult.IsValid ? "True" : "False")
|
|
<< std::endl;
|
|
|
|
VerifyResult ecVerifyDataResult
|
|
= ecCryptoClient.VerifyData(SignatureAlgorithm::ES256K, data, ecSignDataResult.Signature)
|
|
.Value;
|
|
std::cout << " - Verified the signature using the algorithm "
|
|
<< ecVerifyDataResult.Algorithm.ToString() << ", with key "
|
|
<< ecVerifyDataResult.KeyId
|
|
<< ". Signature is valid: " << (ecVerifyDataResult.IsValid ? "True" : "False")
|
|
<< std::endl;
|
|
}
|
|
catch (Azure::Core::RequestFailedException const& e)
|
|
{
|
|
auto const b = e.RawResponse->GetBody();
|
|
std::cout << "Error: " + std::string(b.begin(), b.end());
|
|
returnValue = 1;
|
|
}
|
|
|
|
// Delete the key
|
|
auto deleteOperation = keyClient.StartDeleteKey(rsaKeyName);
|
|
auto ecDeleteOperation = keyClient.StartDeleteKey(ecKeyName);
|
|
deleteOperation.PollUntilDone(2min);
|
|
ecDeleteOperation.PollUntilDone(2min);
|
|
keyClient.PurgeDeletedKey(rsaKeyName);
|
|
keyClient.PurgeDeletedKey(ecKeyName);
|
|
|
|
return returnValue;
|
|
}
|