m2m模型翻译
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

81 lines
3.0 KiB

6 months ago
  1. from __future__ import absolute_import
  2. import base64
  3. import hashlib
  4. import hmac
  5. import uuid
  6. from kafka.vendor import six
  7. if six.PY2:
  8. def xor_bytes(left, right):
  9. return bytearray(ord(lb) ^ ord(rb) for lb, rb in zip(left, right))
  10. else:
  11. def xor_bytes(left, right):
  12. return bytes(lb ^ rb for lb, rb in zip(left, right))
  13. class ScramClient:
  14. MECHANISMS = {
  15. 'SCRAM-SHA-256': hashlib.sha256,
  16. 'SCRAM-SHA-512': hashlib.sha512
  17. }
  18. def __init__(self, user, password, mechanism):
  19. self.nonce = str(uuid.uuid4()).replace('-', '')
  20. self.auth_message = ''
  21. self.salted_password = None
  22. self.user = user
  23. self.password = password.encode('utf-8')
  24. self.hashfunc = self.MECHANISMS[mechanism]
  25. self.hashname = ''.join(mechanism.lower().split('-')[1:3])
  26. self.stored_key = None
  27. self.client_key = None
  28. self.client_signature = None
  29. self.client_proof = None
  30. self.server_key = None
  31. self.server_signature = None
  32. def first_message(self):
  33. client_first_bare = 'n={},r={}'.format(self.user, self.nonce)
  34. self.auth_message += client_first_bare
  35. return 'n,,' + client_first_bare
  36. def process_server_first_message(self, server_first_message):
  37. self.auth_message += ',' + server_first_message
  38. params = dict(pair.split('=', 1) for pair in server_first_message.split(','))
  39. server_nonce = params['r']
  40. if not server_nonce.startswith(self.nonce):
  41. raise ValueError("Server nonce, did not start with client nonce!")
  42. self.nonce = server_nonce
  43. self.auth_message += ',c=biws,r=' + self.nonce
  44. salt = base64.b64decode(params['s'].encode('utf-8'))
  45. iterations = int(params['i'])
  46. self.create_salted_password(salt, iterations)
  47. self.client_key = self.hmac(self.salted_password, b'Client Key')
  48. self.stored_key = self.hashfunc(self.client_key).digest()
  49. self.client_signature = self.hmac(self.stored_key, self.auth_message.encode('utf-8'))
  50. self.client_proof = xor_bytes(self.client_key, self.client_signature)
  51. self.server_key = self.hmac(self.salted_password, b'Server Key')
  52. self.server_signature = self.hmac(self.server_key, self.auth_message.encode('utf-8'))
  53. def hmac(self, key, msg):
  54. return hmac.new(key, msg, digestmod=self.hashfunc).digest()
  55. def create_salted_password(self, salt, iterations):
  56. self.salted_password = hashlib.pbkdf2_hmac(
  57. self.hashname, self.password, salt, iterations
  58. )
  59. def final_message(self):
  60. return 'c=biws,r={},p={}'.format(self.nonce, base64.b64encode(self.client_proof).decode('utf-8'))
  61. def process_server_final_message(self, server_final_message):
  62. params = dict(pair.split('=', 1) for pair in server_final_message.split(','))
  63. if self.server_signature != base64.b64decode(params['v'].encode('utf-8')):
  64. raise ValueError("Server sent wrong signature!")