jwk.h 5.2 KB

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