|
import binascii |
|
from . import der |
|
from ._compat import compat26_str, int_to_bytes |
|
|
|
_SSH_ED25519 = b"ssh-ed25519" |
|
_SK_MAGIC = b"openssh-key-v1\0" |
|
_NONE = b"none" |
|
|
|
|
|
def _get_key_type(name): |
|
if name == "Ed25519": |
|
return _SSH_ED25519 |
|
else: |
|
raise ValueError("Unsupported key type") |
|
|
|
|
|
class _Serializer: |
|
def __init__(self): |
|
self.bytes = b"" |
|
|
|
def put_raw(self, val): |
|
self.bytes += val |
|
|
|
def put_u32(self, val): |
|
self.bytes += int_to_bytes(val, length=4, byteorder="big") |
|
|
|
def put_str(self, val): |
|
self.put_u32(len(val)) |
|
self.bytes += val |
|
|
|
def put_pad(self, blklen=8): |
|
padlen = blklen - (len(self.bytes) % blklen) |
|
self.put_raw(bytearray(range(1, 1 + padlen))) |
|
|
|
def encode(self): |
|
return binascii.b2a_base64(compat26_str(self.bytes)) |
|
|
|
def tobytes(self): |
|
return self.bytes |
|
|
|
def topem(self): |
|
return der.topem(self.bytes, "OPENSSH PRIVATE KEY") |
|
|
|
|
|
def serialize_public(name, pub): |
|
serial = _Serializer() |
|
ktype = _get_key_type(name) |
|
serial.put_str(ktype) |
|
serial.put_str(pub) |
|
return b" ".join([ktype, serial.encode()]) |
|
|
|
|
|
def serialize_private(name, pub, priv): |
|
|
|
spub = _Serializer() |
|
ktype = _get_key_type(name) |
|
spub.put_str(ktype) |
|
spub.put_str(pub) |
|
|
|
|
|
spriv = _Serializer() |
|
checksum = 0 |
|
spriv.put_u32(checksum) |
|
spriv.put_u32(checksum) |
|
spriv.put_raw(spub.tobytes()) |
|
spriv.put_str(priv + pub) |
|
comment = b"" |
|
spriv.put_str(comment) |
|
spriv.put_pad() |
|
|
|
|
|
main = _Serializer() |
|
main.put_raw(_SK_MAGIC) |
|
ciphername = kdfname = _NONE |
|
main.put_str(ciphername) |
|
main.put_str(kdfname) |
|
nokdf = 0 |
|
main.put_u32(nokdf) |
|
nkeys = 1 |
|
main.put_u32(nkeys) |
|
main.put_str(spub.tobytes()) |
|
main.put_str(spriv.tobytes()) |
|
return main.topem() |
|
|