1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138
|
// Copyright 2014 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef COMPONENTS_WEBCRYPTO_JWK_H_
#define COMPONENTS_WEBCRYPTO_JWK_H_
#include <stdint.h>
#include <memory>
#include <vector>
#include "base/values.h"
#include "third_party/WebKit/public/platform/WebCrypto.h"
namespace webcrypto {
class CryptoData;
class Status;
// Helper class for parsing a JWK from JSON.
//
// This primarily exists to ensure strict enforcement of the JWK schema, as the
// type and presence of particular members is security relevant. For example,
// GetString() will ensure a given JSON member is present and is a string type,
// and will fail if these conditions aren't met.
//
// Users of JwkReader must call Init() successfully before any other method can
// be called.
class JwkReader {
public:
JwkReader();
~JwkReader();
// Initializes a JWK reader by parsing the JSON |bytes|. To succeed, the JWK
// must:
// * Have "kty" matching |expected_kty|
// * Have "ext" compatible with |expected_extractable|
// * Have usages ("use", "key_ops") compatible with |expected_usages|
// * Have an "alg" matching |expected_alg|
//
// NOTE: If |expected_alg| is empty, then the test on "alg" is skipped.
Status Init(const CryptoData& bytes,
bool expected_extractable,
blink::WebCryptoKeyUsageMask expected_usages,
const std::string& expected_kty,
const std::string& expected_alg);
// Returns true if the member |member_name| is present.
bool HasMember(const std::string& member_name) const;
// Extracts the required string member |member_name| and saves the result to
// |*result|. If the member does not exist or is not a string, returns an
// error.
Status GetString(const std::string& member_name, std::string* result) const;
// Extracts the optional string member |member_name| and saves the result to
// |*result| if it was found. If the member exists and is not a string,
// returns an error. Otherwise returns success, and sets |*member_exists| if
// it was found.
Status GetOptionalString(const std::string& member_name,
std::string* result,
bool* member_exists) const;
// Extracts the optional array member |member_name| and saves the result to
// |*result| if it was found. If the member exists and is not an array,
// returns an error. Otherwise returns success, and sets |*member_exists| if
// it was found.
//
// NOTE: |*result| is owned by the JwkReader.
Status GetOptionalList(const std::string& member_name,
base::ListValue** result,
bool* member_exists) const;
// Extracts the required string member |member_name| and saves the
// base64url-decoded bytes to |*result|. If the member does not exist or is
// not a string, or could not be base64url-decoded, returns an error.
Status GetBytes(const std::string& member_name, std::string* result) const;
// Extracts the required base64url member, which is interpreted as being a
// big-endian unsigned integer.
//
// Sequences that contain leading zeros will be rejected.
Status GetBigInteger(const std::string& member_name,
std::string* result) const;
// Extracts the optional boolean member |member_name| and saves the result to
// |*result| if it was found. If the member exists and is not a boolean,
// returns an error. Otherwise returns success, and sets |*member_exists| if
// it was found.
Status GetOptionalBool(const std::string& member_name,
bool* result,
bool* member_exists) const;
// Gets the optional algorithm ("alg") string.
Status GetAlg(std::string* alg, bool* has_alg) const;
// Checks if the "alg" member matches |expected_alg|.
Status VerifyAlg(const std::string& expected_alg) const;
private:
std::unique_ptr<base::DictionaryValue> dict_;
};
// Helper class for building the JSON for a JWK.
class JwkWriter {
public:
// Initializes a writer, and sets the standard JWK members as indicated.
// |algorithm| is optional, and is only written if the provided |algorithm| is
// non-empty.
JwkWriter(const std::string& algorithm,
bool extractable,
blink::WebCryptoKeyUsageMask usages,
const std::string& kty);
// Sets a string member |member_name| to |value|.
void SetString(const std::string& member_name, const std::string& value);
// Sets a bytes member |value| to |value| by base64 url-safe encoding it.
void SetBytes(const std::string& member_name, const CryptoData& value);
// Flattens the JWK to JSON (UTF-8 encoded if necessary, however in practice
// it will be ASCII).
void ToJson(std::vector<uint8_t>* utf8_bytes) const;
private:
base::DictionaryValue dict_;
};
// Converts a JWK "key_ops" array to the corresponding WebCrypto usages. Used by
// testing.
Status GetWebCryptoUsagesFromJwkKeyOpsForTest(
const base::ListValue* key_ops,
blink::WebCryptoKeyUsageMask* usages);
} // namespace webcrypto
#endif // COMPONENTS_WEBCRYPTO_JWK_H_
|