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.
 
 
 
 

84 lines
1.9 KiB

  1. import binascii
  2. from . import der
  3. from ._compat import compat26_str, int_to_bytes
  4. _SSH_ED25519 = b"ssh-ed25519"
  5. _SK_MAGIC = b"openssh-key-v1\0"
  6. _NONE = b"none"
  7. def _get_key_type(name):
  8. if name == "Ed25519":
  9. return _SSH_ED25519
  10. else:
  11. raise ValueError("Unsupported key type")
  12. class _Serializer:
  13. def __init__(self):
  14. self.bytes = b""
  15. def put_raw(self, val):
  16. self.bytes += val
  17. def put_u32(self, val):
  18. self.bytes += int_to_bytes(val, length=4, byteorder="big")
  19. def put_str(self, val):
  20. self.put_u32(len(val))
  21. self.bytes += val
  22. def put_pad(self, blklen=8):
  23. padlen = blklen - (len(self.bytes) % blklen)
  24. self.put_raw(bytearray(range(1, 1 + padlen)))
  25. def encode(self):
  26. return binascii.b2a_base64(compat26_str(self.bytes))
  27. def tobytes(self):
  28. return self.bytes
  29. def topem(self):
  30. return der.topem(self.bytes, "OPENSSH PRIVATE KEY")
  31. def serialize_public(name, pub):
  32. serial = _Serializer()
  33. ktype = _get_key_type(name)
  34. serial.put_str(ktype)
  35. serial.put_str(pub)
  36. return b" ".join([ktype, serial.encode()])
  37. def serialize_private(name, pub, priv):
  38. # encode public part
  39. spub = _Serializer()
  40. ktype = _get_key_type(name)
  41. spub.put_str(ktype)
  42. spub.put_str(pub)
  43. # encode private part
  44. spriv = _Serializer()
  45. checksum = 0
  46. spriv.put_u32(checksum)
  47. spriv.put_u32(checksum)
  48. spriv.put_raw(spub.tobytes())
  49. spriv.put_str(priv + pub)
  50. comment = b""
  51. spriv.put_str(comment)
  52. spriv.put_pad()
  53. # top-level structure
  54. main = _Serializer()
  55. main.put_raw(_SK_MAGIC)
  56. ciphername = kdfname = _NONE
  57. main.put_str(ciphername)
  58. main.put_str(kdfname)
  59. nokdf = 0
  60. main.put_u32(nokdf)
  61. nkeys = 1
  62. main.put_u32(nkeys)
  63. main.put_str(spub.tobytes())
  64. main.put_str(spriv.tobytes())
  65. return main.topem()