Jwk deserialize (#2087)
* Remove to_json for jsonWebKey * parse N * Deserialize JWK for EC and OCT * change log * format * fix live tests
This commit is contained in:
parent
c297b63b9b
commit
1ea5afa961
@ -99,31 +99,44 @@ namespace Azure { namespace Core { namespace Json { namespace _internal {
|
||||
destination = decorator(jsonKey[key].get<T>());
|
||||
}
|
||||
}
|
||||
|
||||
template <class T>
|
||||
static inline void SetFromIfPredicate(
|
||||
T const& source,
|
||||
std::function<bool(T const&)> predicate,
|
||||
Azure::Core::Json::_internal::json& jsonKey,
|
||||
std::string const& keyName,
|
||||
std::function<std::string(T const&)> decorator)
|
||||
{
|
||||
if (predicate(source))
|
||||
{
|
||||
jsonKey[keyName] = decorator(source);
|
||||
}
|
||||
}
|
||||
|
||||
template <class T, class R>
|
||||
static inline void SetFromNullable(
|
||||
Azure::Nullable<T> const& source,
|
||||
Azure::Core::Json::_internal::json& jsonKey,
|
||||
std::string const& keyName,
|
||||
std::function<R(T const&)> factory)
|
||||
{
|
||||
if (source)
|
||||
{
|
||||
jsonKey[keyName] = factory(source.Value());
|
||||
}
|
||||
}
|
||||
|
||||
template <class T>
|
||||
static inline void SetFromNullable(
|
||||
Azure::Nullable<T> const& source,
|
||||
Azure::Core::Json::_internal::json& jsonKey,
|
||||
std::string const& keyName)
|
||||
{
|
||||
if (source)
|
||||
{
|
||||
jsonKey[keyName] = source.Value();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
template <class T, class R>
|
||||
static inline void SetFromNullable(
|
||||
Azure::Nullable<T> const& source,
|
||||
Azure::Core::Json::_internal::json& jsonKey,
|
||||
std::string const& keyName,
|
||||
std::function<R(T const&)> factory)
|
||||
{
|
||||
if (source)
|
||||
{
|
||||
jsonKey[keyName] = factory(source.Value());
|
||||
}
|
||||
}
|
||||
|
||||
template <class T>
|
||||
static inline void SetFromNullable(
|
||||
Azure::Nullable<T> const& source,
|
||||
Azure::Core::Json::_internal::json& jsonKey,
|
||||
std::string const& keyName)
|
||||
{
|
||||
if (source)
|
||||
{
|
||||
jsonKey[keyName] = source.Value();
|
||||
}
|
||||
}
|
||||
|
||||
}}}} // namespace Azure::Core::Json::_internal
|
||||
|
||||
@ -2,6 +2,13 @@
|
||||
|
||||
## 4.0.0-beta.2 (Unreleased)
|
||||
|
||||
### New Features
|
||||
|
||||
- Added support for importing and deserializing EC and OCT keys.
|
||||
|
||||
### Breaking Changes
|
||||
|
||||
- Removed `Azure::Security::KeyVault::Keys::JsonWebKey::to_json`.
|
||||
|
||||
## 4.0.0-beta.1 (2021-04-07)
|
||||
|
||||
|
||||
@ -105,4 +105,16 @@ namespace Azure { namespace Security { namespace KeyVault { namespace Keys { nam
|
||||
Azure::Core::Http::RawResponse const& rawResponse);
|
||||
};
|
||||
|
||||
/**************** JWK ************/
|
||||
struct JsonWebKeySerializer
|
||||
{
|
||||
static void JsonWebKeySerialize(
|
||||
JsonWebKey const& jwk,
|
||||
Azure::Core::Json::_internal::json& destJson);
|
||||
|
||||
static void JsonWebDeserialize(
|
||||
JsonWebKey& srcKey,
|
||||
Azure::Core::Json::_internal::json const& jsonParser);
|
||||
};
|
||||
|
||||
}}}}} // namespace Azure::Security::KeyVault::Keys::_detail
|
||||
|
||||
@ -92,11 +92,17 @@ namespace Azure { namespace Security { namespace KeyVault { namespace Keys {
|
||||
/// The RSA private exponent or EC private key.
|
||||
std::vector<uint8_t> D;
|
||||
|
||||
/// Gets the symmetric key.
|
||||
std::vector<uint8_t> K;
|
||||
/// Gets the protected key used with "Bring Your Own Key".
|
||||
std::vector<uint8_t> T;
|
||||
/// Gets the X coordinate of the elliptic curve point.
|
||||
std::vector<uint8_t> X;
|
||||
/// Gets the Y coordinate for the elliptic curve point.
|
||||
std::vector<uint8_t> Y;
|
||||
|
||||
private:
|
||||
std::vector<KeyOperation> m_keyOps;
|
||||
};
|
||||
|
||||
// Define the serialization of a JsonWebKey
|
||||
void to_json(Azure::Core::Json::_internal::json& j, JsonWebKey const& p);
|
||||
|
||||
}}}} // namespace Azure::Security::KeyVault::Keys
|
||||
|
||||
@ -24,39 +24,41 @@ Azure::Security::KeyVault::Keys::_detail::ImportKeyOptionsSerializer::ImportKeyO
|
||||
|
||||
Azure::Core::Json::_internal::json payload;
|
||||
// key
|
||||
payload[_detail::KeyPropertyName] = importKeyOptions.Key;
|
||||
JsonWebKeySerializer::JsonWebKeySerialize(
|
||||
importKeyOptions.Key, payload[_detail::KeyPropertyName]);
|
||||
|
||||
// hsm
|
||||
SetFromNullable(importKeyOptions.HardwareProtected, payload, _detail::HsmPropertyName);
|
||||
JsonOptional::SetFromNullable(
|
||||
importKeyOptions.HardwareProtected, payload, _detail::HsmPropertyName);
|
||||
|
||||
// attributes
|
||||
SetFromNullable<Azure::DateTime, uint64_t>(
|
||||
JsonOptional::SetFromNullable<Azure::DateTime, uint64_t>(
|
||||
importKeyOptions.Properties.CreatedOn,
|
||||
payload[_detail::AttributesPropertyName],
|
||||
_detail::CreatedPropertyName,
|
||||
UnixTimeConverter::DatetimeToUnixTime);
|
||||
SetFromNullable(
|
||||
JsonOptional::SetFromNullable(
|
||||
importKeyOptions.Properties.Enabled,
|
||||
payload[_detail::AttributesPropertyName],
|
||||
_detail::EnabledPropertyName);
|
||||
SetFromNullable<Azure::DateTime, uint64_t>(
|
||||
JsonOptional::SetFromNullable<Azure::DateTime, uint64_t>(
|
||||
importKeyOptions.Properties.ExpiresOn,
|
||||
payload[_detail::AttributesPropertyName],
|
||||
_detail::ExpPropertyName,
|
||||
UnixTimeConverter::DatetimeToUnixTime);
|
||||
SetFromNullable<Azure::DateTime, uint64_t>(
|
||||
JsonOptional::SetFromNullable<Azure::DateTime, uint64_t>(
|
||||
importKeyOptions.Properties.NotBefore,
|
||||
payload[_detail::AttributesPropertyName],
|
||||
_detail::NbfPropertyName,
|
||||
UnixTimeConverter::DatetimeToUnixTime);
|
||||
SetFromNullable(
|
||||
JsonOptional::SetFromNullable(
|
||||
importKeyOptions.Properties.RecoverableDays,
|
||||
payload[_detail::AttributesPropertyName],
|
||||
_detail::RecoverableDaysPropertyName);
|
||||
|
||||
payload[_detail::RecoveryLevelPropertyName] = importKeyOptions.Properties.RecoveryLevel;
|
||||
|
||||
SetFromNullable<Azure::DateTime, uint64_t>(
|
||||
JsonOptional::SetFromNullable<Azure::DateTime, uint64_t>(
|
||||
importKeyOptions.Properties.UpdatedOn,
|
||||
payload[_detail::AttributesPropertyName],
|
||||
_detail::UpdatedPropertyName,
|
||||
|
||||
@ -1,28 +1,128 @@
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
#include <azure/core/internal/json/json_optional.hpp>
|
||||
#include <azure/keyvault/common/internal/base64url.hpp>
|
||||
|
||||
#include "azure/keyvault/keys/details/key_constants.hpp"
|
||||
#include "azure/keyvault/keys/details/key_serializers.hpp"
|
||||
#include "azure/keyvault/keys/json_web_key.hpp"
|
||||
#include "azure/keyvault/keys/key_curve_name.hpp"
|
||||
|
||||
#include <map>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
using namespace Azure::Security::KeyVault::Keys;
|
||||
using namespace Azure::Core::Json::_internal;
|
||||
using namespace Azure::Security::KeyVault::_internal;
|
||||
|
||||
void Azure::Security::KeyVault::Keys::to_json(
|
||||
Azure::Core::Json::_internal::json& j,
|
||||
JsonWebKey const& p)
|
||||
namespace {
|
||||
void ParseStringOperationsToKeyOperations(
|
||||
std::vector<KeyOperation>& keyOperations,
|
||||
std::vector<std::string> const& stringOperations)
|
||||
{
|
||||
j[_detail::KeyTypePropertyName] = KeyType::KeyTypeToString(p.KeyType);
|
||||
j[_detail::NPropertyName] = Base64Url::Base64UrlEncode(p.N);
|
||||
j[_detail::EPropertyName] = Base64Url::Base64UrlEncode(p.E);
|
||||
j[_detail::DPropertyName] = Base64Url::Base64UrlEncode(p.D);
|
||||
j[_detail::DPPropertyName] = Base64Url::Base64UrlEncode(p.DP);
|
||||
j[_detail::DQPropertyName] = Base64Url::Base64UrlEncode(p.DQ);
|
||||
j[_detail::QIPropertyName] = Base64Url::Base64UrlEncode(p.QI);
|
||||
j[_detail::PPropertyName] = Base64Url::Base64UrlEncode(p.P);
|
||||
j[_detail::QPropertyName] = Base64Url::Base64UrlEncode(p.Q);
|
||||
for (std::string const& operation : stringOperations)
|
||||
{
|
||||
keyOperations.emplace_back(KeyOperation(operation));
|
||||
}
|
||||
}
|
||||
|
||||
static inline void AssignBytesIfExists(
|
||||
Azure::Core::Json::_internal::json const& jsonKey,
|
||||
std::string const& keyName,
|
||||
std::vector<uint8_t>& destBytes)
|
||||
{
|
||||
JsonOptional::SetIfExists<std::string, std::vector<uint8_t>>(
|
||||
destBytes, jsonKey, keyName, [](std::string const& value) {
|
||||
return Base64Url::Base64UrlDecode(value);
|
||||
});
|
||||
}
|
||||
|
||||
static inline void WriteJsonIfVectorHasData(
|
||||
std::vector<uint8_t> const& srcVector,
|
||||
Azure::Core::Json::_internal::json& jsonKey,
|
||||
std::string const& keyName)
|
||||
{
|
||||
JsonOptional::SetFromIfPredicate<std::vector<uint8_t> const&>(
|
||||
srcVector,
|
||||
[](std::vector<uint8_t> const& value) { return value.size() > 0; },
|
||||
jsonKey,
|
||||
keyName,
|
||||
Base64Url::Base64UrlEncode);
|
||||
}
|
||||
} // namespace
|
||||
|
||||
void Azure::Security::KeyVault::Keys::_detail::JsonWebKeySerializer::JsonWebKeySerialize(
|
||||
JsonWebKey const& jwk,
|
||||
Azure::Core::Json::_internal::json& destJson)
|
||||
{
|
||||
// kty
|
||||
destJson[_detail::KeyTypePropertyName] = KeyType::KeyTypeToString(jwk.KeyType);
|
||||
|
||||
// ops
|
||||
for (KeyOperation op : jwk.KeyOperations())
|
||||
{
|
||||
destJson[_detail::KeyOpsPropertyName].push_back(op.ToString());
|
||||
}
|
||||
|
||||
// curve name
|
||||
JsonOptional::SetFromNullable<KeyCurveName, std::string>(
|
||||
jwk.CurveName, destJson, _detail::CurveNamePropertyName, [](KeyCurveName const& value) {
|
||||
return value.ToString();
|
||||
});
|
||||
|
||||
// fields
|
||||
WriteJsonIfVectorHasData(jwk.N, destJson, _detail::NPropertyName);
|
||||
WriteJsonIfVectorHasData(jwk.E, destJson, _detail::EPropertyName);
|
||||
WriteJsonIfVectorHasData(jwk.D, destJson, _detail::DPropertyName);
|
||||
WriteJsonIfVectorHasData(jwk.DP, destJson, _detail::DPPropertyName);
|
||||
WriteJsonIfVectorHasData(jwk.DQ, destJson, _detail::DQPropertyName);
|
||||
WriteJsonIfVectorHasData(jwk.QI, destJson, _detail::QIPropertyName);
|
||||
WriteJsonIfVectorHasData(jwk.P, destJson, _detail::PPropertyName);
|
||||
WriteJsonIfVectorHasData(jwk.Q, destJson, _detail::QPropertyName);
|
||||
WriteJsonIfVectorHasData(jwk.X, destJson, _detail::XPropertyName);
|
||||
WriteJsonIfVectorHasData(jwk.Y, destJson, _detail::YPropertyName);
|
||||
WriteJsonIfVectorHasData(jwk.K, destJson, _detail::KPropertyName);
|
||||
WriteJsonIfVectorHasData(jwk.T, destJson, _detail::TPropertyName);
|
||||
}
|
||||
|
||||
void Azure::Security::KeyVault::Keys::_detail::JsonWebKeySerializer::JsonWebDeserialize(
|
||||
JsonWebKey& srcKey,
|
||||
Azure::Core::Json::_internal::json const& jsonParser)
|
||||
{
|
||||
// "Key"
|
||||
if (jsonParser.contains(_detail::KeyPropertyName))
|
||||
{
|
||||
auto const& jsonKey = jsonParser[_detail ::KeyPropertyName];
|
||||
{
|
||||
// key_ops
|
||||
auto keyOperationVector
|
||||
= jsonKey[_detail::KeyOpsPropertyName].get<std::vector<std::string>>();
|
||||
std::vector<KeyOperation> keyOperations;
|
||||
ParseStringOperationsToKeyOperations(keyOperations, keyOperationVector);
|
||||
srcKey.SetKeyOperations(keyOperations);
|
||||
}
|
||||
srcKey.Id = jsonKey[_detail::KeyIdPropertyName].get<std::string>();
|
||||
srcKey.KeyType
|
||||
= KeyType::KeyTypeFromString(jsonKey[_detail::KeyTypePropertyName].get<std::string>());
|
||||
|
||||
JsonOptional::SetIfExists<std::string, KeyCurveName>(
|
||||
srcKey.CurveName, jsonKey, _detail::CurveNamePropertyName, [](std::string const& keyName) {
|
||||
return KeyCurveName(keyName);
|
||||
});
|
||||
|
||||
AssignBytesIfExists(jsonKey, _detail::NPropertyName, srcKey.N);
|
||||
AssignBytesIfExists(jsonKey, _detail::EPropertyName, srcKey.E);
|
||||
AssignBytesIfExists(jsonKey, _detail::DPPropertyName, srcKey.DP);
|
||||
AssignBytesIfExists(jsonKey, _detail::DQPropertyName, srcKey.DQ);
|
||||
AssignBytesIfExists(jsonKey, _detail::QIPropertyName, srcKey.QI);
|
||||
AssignBytesIfExists(jsonKey, _detail::PPropertyName, srcKey.P);
|
||||
AssignBytesIfExists(jsonKey, _detail::QPropertyName, srcKey.Q);
|
||||
AssignBytesIfExists(jsonKey, _detail::DPropertyName, srcKey.D);
|
||||
AssignBytesIfExists(jsonKey, _detail::KPropertyName, srcKey.K);
|
||||
AssignBytesIfExists(jsonKey, _detail::TPropertyName, srcKey.T);
|
||||
AssignBytesIfExists(jsonKey, _detail::XPropertyName, srcKey.X);
|
||||
AssignBytesIfExists(jsonKey, _detail::YPropertyName, srcKey.Y);
|
||||
}
|
||||
}
|
||||
|
||||
@ -20,13 +20,13 @@ std::string KeyRequestParameters::Serialize() const
|
||||
|
||||
Azure::Core::Json::_internal::json payload;
|
||||
// kty
|
||||
SetFromNullable<JsonWebKeyType, std::string>(
|
||||
JsonOptional::SetFromNullable<JsonWebKeyType, std::string>(
|
||||
m_keyType, payload, _detail::KeyTypePropertyName, [](JsonWebKeyType type) {
|
||||
return KeyType::KeyTypeToString(type);
|
||||
});
|
||||
|
||||
// attributes
|
||||
SetFromNullable(
|
||||
JsonOptional::SetFromNullable(
|
||||
m_options.Enabled, payload[_detail::AttributesPropertyName], _detail::EnabledPropertyName);
|
||||
|
||||
/* Optional */
|
||||
@ -39,13 +39,13 @@ std::string KeyRequestParameters::Serialize() const
|
||||
}
|
||||
|
||||
// attributes
|
||||
SetFromNullable<Azure::DateTime, uint64_t>(
|
||||
JsonOptional::SetFromNullable<Azure::DateTime, uint64_t>(
|
||||
m_options.ExpiresOn,
|
||||
payload[_detail::AttributesPropertyName],
|
||||
_detail::ExpPropertyName,
|
||||
UnixTimeConverter::DatetimeToUnixTime);
|
||||
|
||||
SetFromNullable<Azure::DateTime, uint64_t>(
|
||||
JsonOptional::SetFromNullable<Azure::DateTime, uint64_t>(
|
||||
m_options.NotBefore,
|
||||
payload[_detail::AttributesPropertyName],
|
||||
_detail::NbfPropertyName,
|
||||
|
||||
@ -10,25 +10,12 @@
|
||||
|
||||
#include "azure/keyvault/keys/details/key_constants.hpp"
|
||||
#include "azure/keyvault/keys/details/key_serializers.hpp"
|
||||
#include "azure/keyvault/keys/key_curve_name.hpp"
|
||||
#include "azure/keyvault/keys/key_vault_key.hpp"
|
||||
|
||||
using namespace Azure::Security::KeyVault::Keys;
|
||||
using namespace Azure::Core::Json::_internal;
|
||||
using Azure::Security::KeyVault::_internal::UnixTimeConverter;
|
||||
|
||||
namespace {
|
||||
void ParseStringOperationsToKeyOperations(
|
||||
std::vector<KeyOperation>& keyOperations,
|
||||
std::vector<std::string> const& stringOperations)
|
||||
{
|
||||
for (std::string const& operation : stringOperations)
|
||||
{
|
||||
keyOperations.emplace_back(KeyOperation(operation));
|
||||
}
|
||||
}
|
||||
} // namespace
|
||||
|
||||
KeyVaultKey _detail::KeyVaultKeySerializer::KeyVaultKeyDeserialize(
|
||||
std::string const& name,
|
||||
Azure::Core::Http::RawResponse const& rawResponse)
|
||||
@ -59,27 +46,8 @@ void _detail::KeyVaultKeySerializer::KeyVaultKeyDeserialize(
|
||||
KeyVaultKey& key,
|
||||
Azure::Core::Json::_internal::json const& jsonParser)
|
||||
{
|
||||
// "Key"
|
||||
if (jsonParser.contains(_detail::KeyPropertyName))
|
||||
{
|
||||
auto const& jsonKey = jsonParser[_detail::KeyPropertyName];
|
||||
{
|
||||
// key_ops
|
||||
auto keyOperationVector
|
||||
= jsonKey[_detail::KeyOpsPropertyName].get<std::vector<std::string>>();
|
||||
std::vector<KeyOperation> keyOperations;
|
||||
ParseStringOperationsToKeyOperations(keyOperations, keyOperationVector);
|
||||
key.Key.SetKeyOperations(keyOperations);
|
||||
}
|
||||
key.Key.Id = jsonKey[_detail::KeyIdPropertyName].get<std::string>();
|
||||
key.Key.KeyType
|
||||
= KeyType::KeyTypeFromString(jsonKey[_detail::KeyTypePropertyName].get<std::string>());
|
||||
|
||||
JsonOptional::SetIfExists<std::string, KeyCurveName>(
|
||||
key.Key.CurveName, jsonKey, _detail::CurveNamePropertyName, [](std::string const& keyName) {
|
||||
return KeyCurveName(keyName);
|
||||
});
|
||||
}
|
||||
// Deserialize jwk
|
||||
_detail::JsonWebKeySerializer::JsonWebDeserialize(key.Key, jsonParser);
|
||||
|
||||
// Parse URL for the vaultUri, keyVersion
|
||||
_detail::KeyVaultKeySerializer::ParseKeyUrl(key.Properties, key.Key.Id);
|
||||
|
||||
@ -48,7 +48,8 @@ add_executable (
|
||||
)
|
||||
|
||||
if (MSVC)
|
||||
target_compile_options(azure-security-keyvault-keys-test-live PUBLIC /wd6326 /wd26495 /wd26812)
|
||||
# warning C4389: '==': signed/unsigned mismatch
|
||||
target_compile_options(azure-security-keyvault-keys-test-live PUBLIC /wd6326 /wd26495 /wd26812 /wd4389)
|
||||
endif()
|
||||
|
||||
target_link_libraries(azure-security-keyvault-keys-test-live PRIVATE azure-security-keyvault-keys azure-identity gtest gmock)
|
||||
|
||||
@ -8,6 +8,7 @@
|
||||
#include "gtest/gtest.h"
|
||||
|
||||
#include <azure/keyvault/common/internal/base64url.hpp>
|
||||
#include <azure/keyvault/common/keyvault_exception.hpp>
|
||||
#include <azure/keyvault/key_vault.hpp>
|
||||
|
||||
#include "key_client_base_test.hpp"
|
||||
@ -55,8 +56,17 @@ TEST_F(KeyVaultClientTest, ImportKey)
|
||||
"Uyf9s52ywLylhcVE3jfbjOgEozlSwKyhqfXkLpMLWHqOKj9fcfYd4PWKPOgpzWsqjA6fJbBUM"
|
||||
"Yo0CU2G9cWCtVodO7sBJVSIZunWrAlBc");
|
||||
std::string keyName(GetUniqueName());
|
||||
key.CurveName = KeyCurveName::P521();
|
||||
key.SetKeyOperations({KeyOperation::Sign()});
|
||||
|
||||
auto response = keyClient.ImportKey(keyName, key);
|
||||
CheckValidResponse(response);
|
||||
auto const& returnedkey = response.Value;
|
||||
EXPECT_EQ(key.N, returnedkey.Key.N);
|
||||
EXPECT_EQ(key.E, returnedkey.Key.E);
|
||||
EXPECT_EQ(key.CurveName.Value().ToString(), returnedkey.Key.CurveName.Value().ToString());
|
||||
EXPECT_EQ(returnedkey.KeyOperations().size(), 1);
|
||||
EXPECT_EQ(returnedkey.KeyOperations()[0].ToString(), KeyOperation::Sign().ToString());
|
||||
|
||||
{
|
||||
// delete + purge
|
||||
|
||||
Loading…
Reference in New Issue
Block a user