def sign_ssh_data(self, data): key = dsa.DSAPrivateNumbers( x=self.x, public_numbers=dsa.DSAPublicNumbers( y=self.y, parameter_numbers=dsa.DSAParameterNumbers( p=self.p, q=self.q, g=self.g ) ) ).private_key(backend=default_backend()) signer = key.signer(hashes.SHA1()) signer.update(data) r, s = decode_dss_signature(signer.finalize()) m = Message() m.add_string('ssh-dss') # apparently, in rare cases, r or s may be shorter than 20 bytes! rstr = util.deflate_long(r, 0) sstr = util.deflate_long(s, 0) if len(rstr) < 20: rstr = zero_byte * (20 - len(rstr)) + rstr if len(sstr) < 20: sstr = zero_byte * (20 - len(sstr)) + sstr m.add_string(rstr + sstr) return m
def render(self, runner, value): private_key = serialization.load_pem_private_key( force_bytes(value), password=None, backend=default_backend(), ) numbers = private_key.public_key().public_numbers() output = b'' parts = [b'ssh-rsa', deflate_long(numbers.e), deflate_long(numbers.n)] for part in parts: output += struct.pack('>I', len(part)) + part return force_str(b'ssh-rsa ' + base64.b64encode(output) + b'\n')
def _pkcs1imify(self, data): """ turn a 20-byte SHA1 hash into a blob of data as large as the key's N, using PKCS1's \"emsa-pkcs1-v1_5\" encoding. totally bizarre. """ size = len(util.deflate_long(self.n, 0)) filler = max_byte * (size - len(SHA1_DIGESTINFO) - len(data) - 3) return zero_byte + one_byte + filler + zero_byte + SHA1_DIGESTINFO + data
def asbytes(self): key = self.verifying_key m = Message() m.add_string('ecdsa-sha2-nistp256') m.add_string('nistp256') numbers = key.public_numbers() x_bytes = deflate_long(numbers.x, add_sign_padding=False) x_bytes = b'\x00' * (len(x_bytes) - key.curve.key_size // 8) + x_bytes y_bytes = deflate_long(numbers.y, add_sign_padding=False) y_bytes = b'\x00' * (len(y_bytes) - key.curve.key_size // 8) + y_bytes point_str = four_byte + x_bytes + y_bytes m.add_string(point_str) return m.asbytes()
def sign_ssh_data(self, rpool, data): digest = SHA.new(data).digest() rsa = RSA.construct((long(self.n), long(self.e), long(self.d))) sig = util.deflate_long(rsa.sign(self._pkcs1imify(digest), bytes())[0], 0) m = Message() m.add_string('ssh-rsa') m.add_string(sig) return m
def add_mpint(self, z): """ Add a long int to the stream, encoded as an infinite-precision integer. This method only works on positive numbers. :param long z: long int to add """ self.add_string(util.deflate_long(z)) return self
def _pkcs1imify(self, data): """ turn a 20-byte SHA1 hash into a blob of data as large as the key's N, using PKCS1's \"emsa-pkcs1-v1_5\" encoding. totally bizarre. """ SHA1_DIGESTINFO = '\x30\x21\x30\x09\x06\x05\x2b\x0e\x03\x02\x1a\x05\x00\x04\x14' size = len(util.deflate_long(self.n, 0)) filler = '\xff' * (size - len(SHA1_DIGESTINFO) - len(data) - 3) return '\x00\x01' + filler + '\x00' + SHA1_DIGESTINFO + data
def encode_tlv(self, ident, val): # no need to support ident > 31 here self.content += byte_chr(ident) if len(val) > 0x7f: lenstr = util.deflate_long(len(val)) self.content += byte_chr(0x80 + len(lenstr)) + lenstr else: self.content += byte_chr(len(val)) self.content += val
def asbytes(self): key = self.verifying_key m = Message() m.add_string(self.ecdsa_curve.key_format_identifier) m.add_string(self.ecdsa_curve.nist_name) numbers = key.public_numbers() key_size_bytes = (key.curve.key_size + 7) // 8 x_bytes = deflate_long(numbers.x, add_sign_padding=False) x_bytes = b'\x00' * (key_size_bytes - len(x_bytes)) + x_bytes y_bytes = deflate_long(numbers.y, add_sign_padding=False) y_bytes = b'\x00' * (key_size_bytes - len(y_bytes)) + y_bytes point_str = four_byte + x_bytes + y_bytes m.add_string(point_str) return m.asbytes()
def sign_ssh_data(self, rng, data): digest = SHA.new(data).digest() dss = DSA.construct((self.y, self.g, self.p, self.q, self.x)) # generate a suitable k qsize = len(util.deflate_long(self.q, 0)) while True: k = util.inflate_long(rng.read(qsize), 1) if (k > 2) and (k < self.q): break r, s = dss.sign(util.inflate_long(digest, 1), k) m = Message() m.add_string(b'ssh-dss') # apparently, in rare cases, r or s may be shorter than 20 bytes! rstr = util.deflate_long(r, 0) sstr = util.deflate_long(s, 0) if len(rstr) < 20: rstr = b'\x00' * (20 - len(rstr)) + rstr if len(sstr) < 20: sstr = b'\x00' * (20 - len(sstr)) + sstr m.add_string(rstr + sstr) return m
def add_adaptive_int(self, n): """ Add an integer to the stream. :param int n: integer to add """ if n >= Message.big_int: self.packet.write(max_byte) self.add_string(util.deflate_long(n)) else: self.packet.write(struct.pack('>I', n)) return self
def sign_ssh_data(self, data): digest = sha1(data).digest() dss = DSA.construct((long(self.y), long(self.g), long(self.p), long(self.q), long(self.x))) # generate a suitable k qsize = len(util.deflate_long(self.q, 0)) while True: k = util.inflate_long(os.urandom(qsize), 1) if (k > 2) and (k < self.q): break r, s = dss.sign(util.inflate_long(digest, 1), k) m = Message() m.add_string('ssh-dss') # apparently, in rare cases, r or s may be shorter than 20 bytes! rstr = util.deflate_long(r, 0) sstr = util.deflate_long(s, 0) if len(rstr) < 20: rstr = zero_byte * (20 - len(rstr)) + rstr if len(sstr) < 20: sstr = zero_byte * (20 - len(sstr)) + sstr m.add_string(rstr + sstr) return m
def add_mpint(self, z): """ Add a long int to the stream, encoded as an infinite-precision integer. This method only works on positive numbers. @param z: long int to add @type z: long """ b = util.deflate_long(z) self.add_int(len(b)) self.add_bytes(b) return self
def sign_ssh_data(self, data): key = dsa.DSAPrivateNumbers( x=self.x, public_numbers=dsa.DSAPublicNumbers( y=self.y, parameter_numbers=dsa.DSAParameterNumbers( p=self.p, q=self.q, g=self.g))).private_key(backend=default_backend()) sig = key.sign(data, hashes.SHA1()) r, s = decode_dss_signature(sig) m = Message() m.add_string('ssh-dss') # apparently, in rare cases, r or s may be shorter than 20 bytes! rstr = util.deflate_long(r, 0) sstr = util.deflate_long(s, 0) if len(rstr) < 20: rstr = zero_byte * (20 - len(rstr)) + rstr if len(sstr) < 20: sstr = zero_byte * (20 - len(sstr)) + sstr m.add_string(rstr + sstr) return m
def add_int(self, n): """ Add an integer to the stream. @param n: integer to add @type n: int """ if n >= Message.big_int: self.packet.write(max_byte) self.add_string(util.deflate_long(n)) else: self.packet.write(struct.pack(">I", n)) return self
def encode(self, x): if type(x) is bool: if x: self.encode_tlv(1, max_byte) else: self.encode_tlv(1, zero_byte) elif (type(x) is int) or (type(x) is long): self.encode_tlv(2, util.deflate_long(x)) elif type(x) is str: self.encode_tlv(4, x) elif (type(x) is list) or (type(x) is tuple): self.encode_tlv(0x30, self.encode_sequence(x)) else: raise BERException('Unknown type for encoding: %s' % repr(type(x)))
def get_key_pair(filepath, email = "user@domain"): key_pair_file = Path(filepath) if key_pair_file.is_file(): print('Found ssh key') else: print('Key Pair Not Found: ', filepath) print('Generating Key Pair...') key_pair_gen_command = 'ssh-keygen -m pem -t rsa -f {} -q -P "" -C "{}"'.format(str(filepath), email) p = Popen(key_pair_gen_command, shell=True) p.communicate() key = paramiko.RSAKey.from_private_key_file(filepath) output = b'' parts = [b'ssh-rsa', deflate_long(key.public_numbers.e), deflate_long(key.public_numbers.n)] for part in parts: output += struct.pack('>I', len(part)) + part public_key = b'ssh-rsa ' + base64.b64encode(output) + b'\n' file = open("{}.pub".format(PEM_FILEPATH), "r") key_name = file.read().strip().split(' ')[-1] return key_name, public_key
def _generate_x(self): # generate an "x" (1 < x < (p-1)/2). q = (self.p - 1) // 2 qnorm = util.deflate_long(q, 0) qhbyte = byte_ord(qnorm[0]) byte_count = len(qnorm) qmask = 0xff while not (qhbyte & 0x80): qhbyte <<= 1 qmask >>= 1 while True: x_bytes = os.urandom(byte_count) x_bytes = byte_mask(x_bytes[0], qmask) + x_bytes[1:] x = util.inflate_long(x_bytes, 1) if (x > 1) and (x < q): break self.x = x
def _generate_x(self): # generate an "x" (1 < x < (p-1)/2). q = (self.p - 1) // 2 qnorm = util.deflate_long(q, 0) qhbyte = qnorm[0] bytes = len(qnorm) qmask = 0xff while not (qhbyte & 0x80): qhbyte <<= 1 qmask >>= 1 while True: x_bytes = bytearray(self.transport.rng.read(bytes)) x_bytes[0] &= qmask x = util.inflate_long(x_bytes, 1) if (x > 1) and (x < q): break self.x = x
def _generate_x(self): # generate an "x" (1 < x < (p-1)/2). q = (self.p - 1) // 2 qnorm = util.deflate_long(q, 0) qhbyte = ord(qnorm[0]) bytes = len(qnorm) qmask = 0xff while not (qhbyte & 0x80): qhbyte <<= 1 qmask >>= 1 while True: x_bytes = self.transport.rng.read(bytes) x_bytes = chr(ord(x_bytes[0]) & qmask) + x_bytes[1:] x = util.inflate_long(x_bytes, 1) if (x > 1) and (x < q): break self.x = x
def _generate_x(self): # generate an "x" (1 < x < (p-1)/2). q = (self.p - 1) // 2 qnorm = util.deflate_long(q, 0) qhbyte = ord(qnorm[0]) bytes = len(qnorm) qmask = 0xff while not (qhbyte & 0x80): qhbyte <<= 1 qmask >>= 1 while True: self.transport.randpool.stir() x_bytes = self.transport.randpool.get_bytes(bytes) x_bytes = chr(ord(x_bytes[0]) & qmask) + x_bytes[1:] x = util.inflate_long(x_bytes, 1) if (x > 1) and (x < q): break self.x = x