def _write_private_key(self, tag, f, data, password=None): f.write('-----BEGIN %s PRIVATE KEY-----\n' % tag) if password is not None: # since we only support one cipher here, use it cipher_name = list(self._CIPHER_TABLE.keys())[0] cipher = self._CIPHER_TABLE[cipher_name]['cipher'] keysize = self._CIPHER_TABLE[cipher_name]['keysize'] blocksize = self._CIPHER_TABLE[cipher_name]['blocksize'] mode = self._CIPHER_TABLE[cipher_name]['mode'] salt = rng.read(16) key = util.generate_key_bytes(MD5, salt, password, keysize) if len(data) % blocksize != 0: n = blocksize - len(data) % blocksize #data += rng.read(n) # that would make more sense ^, but it confuses openssh. data += zero_byte * n data = cipher.new(key, mode, salt).encrypt(data) f.write('Proc-Type: 4,ENCRYPTED\n') f.write('DEK-Info: %s,%s\n' % (cipher_name, u(hexlify(salt)).upper())) f.write('\n') s = u(encodebytes(data)) # re-wrap to 64-char lines s = ''.join(s.split('\n')) s = '\n'.join([s[i: i + 64] for i in range(0, len(s), 64)]) f.write(s) f.write('\n') f.write('-----END %s PRIVATE KEY-----\n' % tag)
def _write_private_key(self, tag, f, data, password=None): f.write('-----BEGIN %s PRIVATE KEY-----\n' % tag) if password is not None: # since we only support one cipher here, use it cipher_name = list(self._CIPHER_TABLE.keys())[0] cipher = self._CIPHER_TABLE[cipher_name]['cipher'] keysize = self._CIPHER_TABLE[cipher_name]['keysize'] blocksize = self._CIPHER_TABLE[cipher_name]['blocksize'] mode = self._CIPHER_TABLE[cipher_name]['mode'] salt = rng.read(16) key = util.generate_key_bytes(MD5, salt, password, keysize) if len(data) % blocksize != 0: n = blocksize - len(data) % blocksize #data += rng.read(n) # that would make more sense ^, but it confuses openssh. data += zero_byte * n data = cipher.new(key, mode, salt).encrypt(data) f.write('Proc-Type: 4,ENCRYPTED\n') f.write('DEK-Info: %s,%s\n' % (cipher_name, u(hexlify(salt)).upper())) f.write('\n') s = u(encodebytes(data)) # re-wrap to 64-char lines s = ''.join(s.split('\n')) s = '\n'.join([s[i:i + 64] for i in range(0, len(s), 64)]) f.write(s) f.write('\n') f.write('-----END %s PRIVATE KEY-----\n' % tag)
def _build_packet(self, payload): # pad up at least 4 bytes, to nearest block-size (usually 8) bsize = self.__block_size_out padding = 3 + bsize - ((len(payload) + 8) % bsize) packet = struct.pack('>IB', len(payload) + padding + 1, padding) packet += payload if self.__sdctr_out or self.__block_engine_out is None: # cute trick i caught openssh doing: if we're not encrypting or SDCTR mode (RFC4344), # don't waste random bytes for the padding packet += (zero_byte * padding) else: packet += rng.read(padding) return packet
def hash_host(hostname, salt=None): """ Return a "hashed" form of the hostname, as used by OpenSSH when storing hashed hostnames in the known_hosts file. :param str hostname: the hostname to hash :param str salt: optional salt to use when hashing (must be 20 bytes long) :return: the hashed hostname as a `str` """ if salt is None: salt = rng.read(SHA.digest_size) else: if salt.startswith('|1|'): salt = salt.split('|')[2] salt = decodebytes(b(salt)) assert len(salt) == SHA.digest_size hmac = HMAC.HMAC(salt, b(hostname), SHA).digest() hostkey = '|1|%s|%s' % (u(encodebytes(salt)), u(encodebytes(hmac))) return hostkey.replace('\n', '')
def sign_ssh_data(self, rng, data): digest = SHA.new(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(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('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)) if len(sstr) < 20: sstr += zero_byte * (20 - len(sstr)) m.add_string(rstr + sstr) return m
def test_6_random(self): from paramiko.common import rng # just verify that we can pull out 32 bytes and not get an exception. x = rng.read(32) self.assertEquals(len(x), 32)