def test_fromPrivateBlobDSA(self): """ A private DSA key is correctly generated from a private key blob. """ dsaBlob = ( common.NS(b'ssh-dss') + common.MP(keydata.DSAData['p']) + common.MP(keydata.DSAData['q']) + common.MP(keydata.DSAData['g']) + common.MP(keydata.DSAData['y']) + common.MP(keydata.DSAData['x']) ) dsaKey = keys.Key._fromString_PRIVATE_BLOB(dsaBlob) self.assertFalse(dsaKey.isPublic()) self.assertEqual(keydata.DSAData, dsaKey.data()) self.assertEqual( dsaKey, keys.Key._fromString_PRIVATE_BLOB(dsaKey.privateBlob()))
def test_fromBlobDSA(self): """ A public DSA key is correctly generated from a public key blob. """ dsaPublicData = { 'p': keydata.DSAData['p'], 'q': keydata.DSAData['q'], 'g': keydata.DSAData['g'], 'y': keydata.DSAData['y'], } dsaBlob = (common.NS(b'ssh-dss') + common.MP(dsaPublicData['p']) + common.MP(dsaPublicData['q']) + common.MP(dsaPublicData['g']) + common.MP(dsaPublicData['y'])) dsaKey = keys.Key.fromString(dsaBlob) self.assertTrue(dsaKey.isPublic()) self.assertEqual(dsaPublicData, dsaKey.data())
def test_signRSA(self): """ Test that RSA keys return appropriate signatures. """ data = 'data' key, sig = self._signRSA(data) sigData = keys.pkcs1Digest(data, keys.lenSig(key)) v = key.sign(sigData, '')[0] self.assertEqual(sig, common.NS('ssh-rsa') + common.MP(v)) return key, sig
def blob(self): """ Return the public key blob for this key. The blob is the over-the-wire format for public keys: RSA keys:: string 'ssh-rsa' integer e integer n DSA keys:: string 'ssh-dss' integer p integer q integer g integer y @rtype: C{str} """ type = self.type() data = self.data() if type == 'RSA': return (common.NS('ssh-rsa') + common.MP(data['e']) + common.MP(data['n'])) elif type == 'DSA': return (common.NS('ssh-dss') + common.MP(data['p']) + common.MP(data['q']) + common.MP(data['g']) + common.MP(data['y']))
def blob(self): """ Return the public key blob for this key. The blob is the over-the-wire format for public keys: RSA keys:: string 'ssh-rsa' integer e integer n DSA keys:: string 'ssh-dss' integer p integer q integer g integer y @rtype: C{bytes} """ type = self.type() data = self.data() if type == 'RSA': return (common.NS(b'ssh-rsa') + common.MP(data['e']) + common.MP(data['n'])) elif type == 'DSA': return (common.NS(b'ssh-dss') + common.MP(data['p']) + common.MP(data['q']) + common.MP(data['g']) + common.MP(data['y'])) else: raise BadKeyError("unknown key type %s" % (type, ))
def test_privateBlobEC(self): """ L{keys.Key.privateBlob} returns the SSH ptotocol-level format of EC private key. """ from cryptography.hazmat.primitives import serialization self.assertEqual( keys.Key(self.ecObj).privateBlob(), common.NS(keydata.ECDatanistp256['curve']) + common.NS(keydata.ECDatanistp256['curve'][-8:]) + common.NS( self.ecObj.public_key().public_bytes( serialization.Encoding.X962, serialization.PublicFormat.UncompressedPoint)) + common.MP(self.ecObj.private_numbers().private_value) )
def test_fromPrivateBlobECDSA(self): """ A private EC key is correctly generated from a private key blob. """ from cryptography.hazmat.primitives.asymmetric import ec publicNumbers = ec.EllipticCurvePublicNumbers( x=keydata.ECDatanistp256['x'], y=keydata.ECDatanistp256['y'], curve=ec.SECP256R1()) ecblob = ( common.NS(keydata.ECDatanistp256['curve']) + common.NS(keydata.ECDatanistp256['curve'][-8:]) + common.NS(publicNumbers.encode_point()) + common.MP(keydata.ECDatanistp256['privateValue']) ) eckey = keys.Key._fromString_PRIVATE_BLOB(ecblob) self.assertFalse(eckey.isPublic()) self.assertEqual(keydata.ECDatanistp256, eckey.data())
def test_fromPrivateBlobRSA(self): """ A private RSA key is correctly generated from a private key blob. """ rsaBlob = (common.NS(b'ssh-rsa') + common.MP(keydata.RSAData['n']) + common.MP(keydata.RSAData['e']) + common.MP(keydata.RSAData['d']) + common.MP(keydata.RSAData['u']) + common.MP(keydata.RSAData['p']) + common.MP(keydata.RSAData['q'])) rsaKey = keys.Key._fromString_PRIVATE_BLOB(rsaBlob) self.assertFalse(rsaKey.isPublic()) self.assertEqual(keydata.RSAData, rsaKey.data())
def test_fromBlob(self): """ Test that a public key is correctly generated from a public key blob. """ rsaBlob = common.NS('ssh-rsa') + common.MP(2) + common.MP(3) rsaKey = keys.Key.fromString(rsaBlob) dsaBlob = (common.NS('ssh-dss') + common.MP(2) + common.MP(3) + common.MP(4) + common.MP(5)) dsaKey = keys.Key.fromString(dsaBlob) badBlob = common.NS('ssh-bad') self.assertTrue(rsaKey.isPublic()) self.assertEqual(rsaKey.data(), {'e': 2L, 'n': 3L}) self.assertTrue(dsaKey.isPublic()) self.assertEqual(dsaKey.data(), {'p': 2L, 'q': 3L, 'g': 4L, 'y': 5L}) self.assertRaises(keys.BadKeyError, keys.Key.fromString, badBlob)
def test_privateBlobRSA(self): """ L{keys.Key.privateBlob} returns the SSH protocol-level format of an RSA private key. """ numbers = self.rsaObj.private_numbers() self.assertEqual( keys.Key(self.rsaObj).privateBlob(), common.NS(b'ssh-rsa') + common.MP(numbers.public_numbers.n) + common.MP(numbers.public_numbers.e) + common.MP(numbers.d) + common.MP(numbers.iqmp) + common.MP(numbers.p) + common.MP(numbers.q) )
def __repr__(self): """ Return a pretty representation of this object. """ if self.type() == 'EC': data = self.data() name = data['curve'].decode('utf-8') if self.isPublic(): out = '<Elliptic Curve Public Key (%s bits)' % (name[-3:],) else: out = '<Elliptic Curve Private Key (%s bits)' % (name[-3:],) for k, v in sorted(data.items()): if _PY3 and k == 'curve': out += "\ncurve:\n\t%s" % (name,) else: out += "\n%s:\n\t%s" % (k, v) return out + ">\n" else: lines = [ '<%s %s (%s bits)' % ( nativeString(self.type()), self.isPublic() and 'Public Key' or 'Private Key', self._keyObject.key_size)] for k, v in sorted(self.data().items()): lines.append('attr %s:' % (k,)) by = common.MP(v)[4:] while by: m = by[:15] by = by[15:] o = '' for c in iterbytes(m): o = o + '%02x:' % (ord(c),) if len(m) < 15: o = o[:-1] lines.append('\t' + o) lines[-1] = lines[-1] + '>' return '\n'.join(lines)
def test_privateBlobRSA(self): """ L{keys.Key.privateBlob} returns the SSH protocol-level format of an RSA private key. """ from cryptography.hazmat.primitives.asymmetric import rsa numbers = self.rsaObj.private_numbers() u = rsa.rsa_crt_iqmp(numbers.q, numbers.p) self.assertEqual( keys.Key(self.rsaObj).privateBlob(), common.NS(b'ssh-rsa') + common.MP(self.rsaObj.private_numbers().public_numbers.n) + common.MP(self.rsaObj.private_numbers().public_numbers.e) + common.MP(self.rsaObj.private_numbers().d) + common.MP(u) + common.MP(self.rsaObj.private_numbers().p) + common.MP(self.rsaObj.private_numbers().q))
def __repr__(self): """ Return a pretty representation of this object. """ lines = [ '<%s %s (%s bits)' % (self.type(), self.isPublic() and 'Public Key' or 'Private Key', self.keyObject.size()) ] for k, v in sorted(self.data().items()): lines.append('attr %s:' % k) by = common.MP(v)[4:] while by: m = by[:15] by = by[15:] o = '' for c in m: o = o + '%02x:' % ord(c) if len(m) < 15: o = o[:-1] lines.append('\t' + o) lines[-1] = lines[-1] + '>' return '\n'.join(lines)
def blob(self): """ Return the public key blob for this key. The blob is the over-the-wire format for public keys. SECSH-TRANS RFC 4253 Section 6.6. RSA keys:: string 'ssh-rsa' integer e integer n DSA keys:: string 'ssh-dss' integer p integer q integer g integer y EC keys:: string 'ecdsa-sha2-[identifier]' integer x integer y identifier is the standard NIST curve name @rtype: L{bytes} """ type = self.type() data = self.data() if type == 'RSA': return (common.NS(b'ssh-rsa') + common.MP(data['e']) + common.MP(data['n'])) elif type == 'DSA': return (common.NS(b'ssh-dss') + common.MP(data['p']) + common.MP(data['q']) + common.MP(data['g']) + common.MP(data['y'])) else: # EC byteLength = (self._keyObject.curve.key_size + 7) // 8 return ( common.NS(data['curve']) + common.NS(data["curve"][-8:]) + common.NS(b'\x04' + utils.int_to_bytes(data['x'], byteLength) + utils.int_to_bytes(data['y'], byteLength)))
def test_fromPrivateBlob(self): """ Test that a private key is correctly generated from a private key blob. """ rsaBlob = (common.NS('ssh-rsa') + common.MP(2) + common.MP(3) + common.MP(4) + common.MP(5) + common.MP(6) + common.MP(7)) rsaKey = keys.Key._fromString_PRIVATE_BLOB(rsaBlob) dsaBlob = (common.NS('ssh-dss') + common.MP(2) + common.MP(3) + common.MP(4) + common.MP(5) + common.MP(6)) dsaKey = keys.Key._fromString_PRIVATE_BLOB(dsaBlob) badBlob = common.NS('ssh-bad') self.assertFalse(rsaKey.isPublic()) self.assertEqual(rsaKey.data(), { 'n': 2L, 'e': 3L, 'd': 4L, 'u': 5L, 'p': 6L, 'q': 7L }) self.assertFalse(dsaKey.isPublic()) self.assertEqual(dsaKey.data(), { 'p': 2L, 'q': 3L, 'g': 4L, 'y': 5L, 'x': 6L }) self.assertRaises(keys.BadKeyError, keys.Key._fromString_PRIVATE_BLOB, badBlob)
def _toString_LSH(self): """ Return a public or private LSH key. See _fromString_PUBLIC_LSH and _fromString_PRIVATE_LSH for the key formats. @rtype: C{str} """ data = self.data() if self.isPublic(): if self.type() == 'RSA': keyData = sexpy.pack([[ 'public-key', [ 'rsa-pkcs1-sha1', ['n', common.MP(data['n'])[4:]], ['e', common.MP(data['e'])[4:]] ] ]]) elif self.type() == 'DSA': keyData = sexpy.pack([[ 'public-key', [ 'dsa', ['p', common.MP(data['p'])[4:]], ['q', common.MP(data['q'])[4:]], ['g', common.MP(data['g'])[4:]], ['y', common.MP(data['y'])[4:]] ] ]]) return '{' + base64.encodestring(keyData).replace('\n', '') + '}' else: if self.type() == 'RSA': p, q = data['p'], data['q'] return sexpy.pack([[ 'private-key', [ 'rsa-pkcs1', ['n', common.MP(data['n'])[4:]], ['e', common.MP(data['e'])[4:]], ['d', common.MP(data['d'])[4:]], ['p', common.MP(q)[4:]], ['q', common.MP(p)[4:]], ['a', common.MP(data['d'] % (q - 1))[4:]], ['b', common.MP(data['d'] % (p - 1))[4:]], ['c', common.MP(data['u'])[4:]] ] ]]) elif self.type() == 'DSA': return sexpy.pack([[ 'private-key', [ 'dsa', ['p', common.MP(data['p'])[4:]], ['q', common.MP(data['q'])[4:]], ['g', common.MP(data['g'])[4:]], ['y', common.MP(data['y'])[4:]], ['x', common.MP(data['x'])[4:]] ] ]])
def privateBlob(self): """ Return the private key blob for this key. The blob is the over-the-wire format for private keys: RSA keys:: string 'ssh-rsa' integer n integer e integer d integer u integer p integer q DSA keys:: string 'ssh-dss' integer p integer q integer g integer y integer x """ type = self.type() data = self.data() if type == 'RSA': return (common.NS('ssh-rsa') + common.MP(data['n']) + common.MP(data['e']) + common.MP(data['d']) + common.MP(data['u']) + common.MP(data['p']) + common.MP(data['q'])) elif type == 'DSA': return (common.NS('ssh-dss') + common.MP(data['p']) + common.MP(data['q']) + common.MP(data['g']) + common.MP(data['y']) + common.MP(data['x']))
def _toString_LSH(self): """ Return a public or private LSH key. See _fromString_PUBLIC_LSH and _fromString_PRIVATE_LSH for the key formats. @rtype: L{bytes} """ data = self.data() type = self.type() if self.isPublic(): if type == 'RSA': keyData = sexpy.pack([[b'public-key', [b'rsa-pkcs1-sha1', [b'n', common.MP(data['n'])[4:]], [b'e', common.MP(data['e'])[4:]]]]]) elif type == 'DSA': keyData = sexpy.pack([[b'public-key', [b'dsa', [b'p', common.MP(data['p'])[4:]], [b'q', common.MP(data['q'])[4:]], [b'g', common.MP(data['g'])[4:]], [b'y', common.MP(data['y'])[4:]]]]]) else: raise BadKeyError("unknown key type %s" % (type,)) return (b'{' + encodebytes(keyData).replace(b'\n', b'') + b'}') else: if type == 'RSA': p, q = data['p'], data['q'] return sexpy.pack([[b'private-key', [b'rsa-pkcs1', [b'n', common.MP(data['n'])[4:]], [b'e', common.MP(data['e'])[4:]], [b'd', common.MP(data['d'])[4:]], [b'p', common.MP(q)[4:]], [b'q', common.MP(p)[4:]], [b'a', common.MP( data['d'] % (q - 1))[4:]], [b'b', common.MP( data['d'] % (p - 1))[4:]], [b'c', common.MP(data['u'])[4:]]]]]) elif type == 'DSA': return sexpy.pack([[b'private-key', [b'dsa', [b'p', common.MP(data['p'])[4:]], [b'q', common.MP(data['q'])[4:]], [b'g', common.MP(data['g'])[4:]], [b'y', common.MP(data['y'])[4:]], [b'x', common.MP(data['x'])[4:]]]]]) else: raise BadKeyError("unknown key type %s'" % (type,))
def privateBlob(self): """ Return the private key blob for this key. The blob is the over-the-wire format for private keys: Specification in OpenSSH PROTOCOL.agent RSA keys:: string 'ssh-rsa' integer n integer e integer d integer u integer p integer q DSA keys:: string 'ssh-dss' integer p integer q integer g integer y integer x EC keys:: string 'ecdsa-sha2-[identifier]' integer x integer y integer privateValue identifier is the NIST standard curve name. """ type = self.type() data = self.data() if type == 'RSA': return (common.NS(b'ssh-rsa') + common.MP(data['n']) + common.MP(data['e']) + common.MP(data['d']) + common.MP(data['u']) + common.MP(data['p']) + common.MP(data['q'])) elif type == 'DSA': return (common.NS(b'ssh-dss') + common.MP(data['p']) + common.MP(data['q']) + common.MP(data['g']) + common.MP(data['y']) + common.MP(data['x'])) else: # EC return (common.NS(data['curve']) + common.MP(data['x']) + common.MP(data['y']) + common.MP(data['privateValue']))
def privateBlob(self): """ Return the private key blob for this key. The blob is the over-the-wire format for private keys: Specification in OpenSSH PROTOCOL.agent RSA keys:: string 'ssh-rsa' integer n integer e integer d integer u integer p integer q DSA keys:: string 'ssh-dss' integer p integer q integer g integer y integer x """ type = self.type() data = self.data() if type == 'RSA': return (common.NS(b'ssh-rsa') + common.MP(data['n']) + common.MP(data['e']) + common.MP(data['d']) + common.MP(data['u']) + common.MP(data['p']) + common.MP(data['q'])) elif type == 'DSA': return (common.NS(b'ssh-dss') + common.MP(data['p']) + common.MP(data['q']) + common.MP(data['g']) + common.MP(data['y']) + common.MP(data['x'])) else: raise BadKeyError("unknown key type %s" % (type, ))