Não pode escolher mais do que 25 tópicos Os tópicos devem começar com uma letra ou um número, podem incluir traços ('-') e podem ter até 35 caracteres.
 
 
 
 

132 linhas
3.9 KiB

  1. # -*- coding: utf-8 -*-
  2. #
  3. # Copyright 2017 Gehirn Inc.
  4. #
  5. # Licensed under the Apache License, Version 2.0 (the "License");
  6. # you may not use this file except in compliance with the License.
  7. # You may obtain a copy of the License at
  8. #
  9. # http://www.apache.org/licenses/LICENSE-2.0
  10. #
  11. # Unless required by applicable law or agreed to in writing, software
  12. # distributed under the License is distributed on an "AS IS" BASIS,
  13. # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  14. # See the License for the specific language governing permissions and
  15. # limitations under the License.
  16. import hashlib
  17. import hmac
  18. from typing import Callable
  19. from cryptography.hazmat.primitives.hashes import (
  20. SHA256,
  21. SHA384,
  22. SHA512,
  23. )
  24. from .exceptions import InvalidKeyTypeError
  25. from .jwk import AbstractJWKBase
  26. def std_hash_by_alg(alg: str) -> Callable[[bytes], object]:
  27. if alg.endswith('S256'):
  28. return hashlib.sha256
  29. if alg.endswith('S384'):
  30. return hashlib.sha384
  31. if alg.endswith('S512'):
  32. return hashlib.SHA512
  33. raise ValueError('{} is not supported'.format(alg))
  34. class AbstractSigningAlgorithm:
  35. def sign(self, message: bytes, key: AbstractJWKBase) -> bytes:
  36. raise NotImplementedError() # pragma: no cover
  37. def verify(self, message: bytes, key: AbstractJWKBase,
  38. signature: bytes) -> bool:
  39. raise NotImplementedError() # pragma: no cover
  40. class NoneAlgorithm(AbstractSigningAlgorithm):
  41. def sign(self, message: bytes, key: AbstractJWKBase) -> bytes:
  42. return b''
  43. def verify(self, message: bytes, key: AbstractJWKBase,
  44. signature: bytes) -> bool:
  45. return hmac.compare_digest(signature, b'')
  46. none = NoneAlgorithm()
  47. class HMACAlgorithm(AbstractSigningAlgorithm):
  48. def __init__(self, hash_fun: Callable) -> None:
  49. self.hash_fun = hash_fun
  50. def _check_key(self, key: AbstractJWKBase) -> None:
  51. if key.get_kty() != 'oct':
  52. raise InvalidKeyTypeError((
  53. 'an octet key is required, but passed is {}'
  54. ).format(key.get_kty()))
  55. def _sign(self, message: bytes, key: bytes) -> bytes:
  56. return hmac.new(key, message, self.hash_fun).digest()
  57. def sign(self, message: bytes, key: AbstractJWKBase) -> bytes:
  58. self._check_key(key)
  59. return key.sign(message, signer=self._sign)
  60. def verify(self, message: bytes, key: AbstractJWKBase,
  61. signature: bytes) -> bool:
  62. self._check_key(key)
  63. return key.verify(message, signature, signer=self._sign)
  64. HS256 = HMACAlgorithm(hashlib.sha256)
  65. HS384 = HMACAlgorithm(hashlib.sha384)
  66. HS512 = HMACAlgorithm(hashlib.sha512)
  67. class RSAAlgorithm(AbstractSigningAlgorithm):
  68. def __init__(self, hash_fun: object) -> None:
  69. self.hash_fun = hash_fun
  70. def _check_key(self, key: AbstractJWKBase, must_sign_key=False) -> None:
  71. if key.get_kty() != 'RSA':
  72. raise InvalidKeyTypeError((
  73. 'a RSA key is required, but passed is {}'
  74. ).format(key.get_kty()))
  75. if must_sign_key and not key.is_sign_key():
  76. raise InvalidKeyTypeError(
  77. 'a RSA private key is required, but passed is RSA public key')
  78. def sign(self, message: bytes, key: AbstractJWKBase) -> bytes:
  79. self._check_key(key, must_sign_key=True)
  80. return key.sign(message, hash_fun=self.hash_fun)
  81. def verify(self, message: bytes, key: AbstractJWKBase,
  82. signature: bytes) -> bool:
  83. self._check_key(key)
  84. return key.verify(message, signature, hash_fun=self.hash_fun)
  85. RS256 = RSAAlgorithm(SHA256)
  86. RS384 = RSAAlgorithm(SHA384)
  87. RS512 = RSAAlgorithm(SHA512)
  88. def supported_signing_algorithms():
  89. # NOTE(yosida95): exclude vulnerable 'none' algorithm by default.
  90. return {
  91. 'HS256': HS256,
  92. 'HS384': HS384,
  93. 'HS512': HS512,
  94. 'RS256': RS256,
  95. 'RS384': RS384,
  96. 'RS512': RS512,
  97. }