def load_private(self, data: memoryview, pubfields) -> typing.Tuple[dsa.DSAPrivateKey, memoryview]: """Make DSA private key from data.""" (p, q, g, y), data = self.get_public(data) x, data = _get_mpint(data) if (p, q, g, y) != pubfields: raise ValueError("Corrupt data: dsa field mismatch") parameter_numbers = dsa.DSAParameterNumbers(p, q, g) public_numbers = dsa.DSAPublicNumbers(y, parameter_numbers) self._validate(public_numbers) private_numbers = dsa.DSAPrivateNumbers(x, public_numbers) private_key = private_numbers.private_key() return private_key, data
def write_private_key_file(self, filename, password=None): 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()) self._write_private_key_file( filename, key, serialization.PrivateFormat.TraditionalOpenSSL, password=password)
def _deserialize_dsa_private_key(stream: typing.BinaryIO) -> dsa.DSAPrivateKey: dsa_p = _sshbuf_get_bignum2(stream) dsa_q = _sshbuf_get_bignum2(stream) dsa_g = _sshbuf_get_bignum2(stream) dsa_pub_key = _sshbuf_get_bignum2(stream) dsa_priv_key = _sshbuf_get_bignum2(stream) parameter_numbers = dsa.DSAParameterNumbers(p=dsa_p, q=dsa_q, g=dsa_g) public_numbers = dsa.DSAPublicNumbers(y=dsa_pub_key, parameter_numbers=parameter_numbers) private_numbers = dsa.DSAPrivateNumbers(x=dsa_priv_key, public_numbers=public_numbers) # ignoring mypy error that DSAPrivateNumbers does not have private_key() - it does. return private_numbers.private_key( backend=default_backend()) # type: ignore
def test_dsa_signing(self, vector, backend): digest_algorithm = vector['digest_algorithm'].replace("-", "") algorithm = self._algorithms_dict[digest_algorithm] _skip_if_dsa_not_supported(backend, algorithm, vector['p'], vector['q'], vector['g']) private_key = dsa.DSAPrivateNumbers( public_numbers=dsa.DSAPublicNumbers( parameter_numbers=dsa.DSAParameterNumbers( vector['p'], vector['q'], vector['g']), y=vector['y']), x=vector['x']).private_key(backend) signature = private_key.sign(vector['msg'], algorithm()) assert signature private_key.public_key().verify(signature, vector['msg'], algorithm())
def test_large_p(self, backend): key = load_vectors_from_file( os.path.join("asymmetric", "PEM_Serialization", "dsa_4096.pem"), lambda pemfile: serialization.load_pem_private_key( pemfile.read(), None, backend), mode="rb") pn = key.private_numbers() assert pn.public_numbers.parameter_numbers.p.bit_length() == 4096 # Turn it back into a key to confirm that values this large pass # verification dsa.DSAPrivateNumbers(public_numbers=dsa.DSAPublicNumbers( parameter_numbers=dsa.DSAParameterNumbers( p=pn.public_numbers.parameter_numbers.p, q=pn.public_numbers.parameter_numbers.q, g=pn.public_numbers.parameter_numbers.g, ), y=pn.public_numbers.y), x=pn.x).private_key(backend)
def test_private_numbers_ne(self): pub = dsa.DSAPublicNumbers(1, dsa.DSAParameterNumbers(1, 2, 3)) priv = dsa.DSAPrivateNumbers(1, pub) assert priv != dsa.DSAPrivateNumbers( 2, dsa.DSAPublicNumbers(1, dsa.DSAParameterNumbers(1, 2, 3))) assert priv != dsa.DSAPrivateNumbers( 1, dsa.DSAPublicNumbers(2, dsa.DSAParameterNumbers(1, 2, 3))) assert priv != dsa.DSAPrivateNumbers( 1, dsa.DSAPublicNumbers(1, dsa.DSAParameterNumbers(2, 2, 3))) assert priv != dsa.DSAPrivateNumbers( 1, dsa.DSAPublicNumbers(1, dsa.DSAParameterNumbers(1, 3, 3))) assert priv != dsa.DSAPrivateNumbers( 1, dsa.DSAPublicNumbers(1, dsa.DSAParameterNumbers(1, 2, 4))) assert priv != object()
def convert_key(cls, packet, private=False): if isinstance(packet, RSAPrivateKey) or isinstance( packet, RSAPublicKey) or isinstance( packet, DSAPublicKey) or isinstance(packet, DSAPrivateKey): if (not private) and (isinstance(packet, DSAPrivateKey) or isinstance(packet, RSAPrivateKey)): return packet.public_key() else: return packet packet = cls._parse_packet(packet) if isinstance(packet, OpenPGP.Message): packet = packet[0] if packet.key_algorithm_name() == 'DSA': params = dsa.DSAParameterNumbers( cls._bytes_to_long(packet.key['p']), cls._bytes_to_long(packet.key['q']), cls._bytes_to_long(packet.key['g'])) public = dsa.DSAPublicNumbers(cls._bytes_to_long(packet.key['y']), params) if private: return dsa.DSAPrivateNumbers( cls._bytes_to_long(packet.key['x']), public).private_key(openssl.backend) else: return public.public_key(openssl.backend) else: # RSA public = rsa.RSAPublicNumbers(cls._bytes_to_long(packet.key['e']), cls._bytes_to_long(packet.key['n'])) if private: d = cls._bytes_to_long(packet.key['d']) p = cls._bytes_to_long(packet.key['q']) q = cls._bytes_to_long(packet.key['p']) dmp1 = rsa.rsa_crt_dmp1(d, p) dmq1 = rsa.rsa_crt_dmp1(d, q) u = cls._bytes_to_long(packet.key['u']) return rsa.RSAPrivateNumbers(p, q, d, dmp1, dmq1, u, public).private_key( default_backend()) else: return public.public_key(default_backend())
def private_numbers(self): p = self._backend._ffi.new("BIGNUM **") q = self._backend._ffi.new("BIGNUM **") g = self._backend._ffi.new("BIGNUM **") pub_key = self._backend._ffi.new("BIGNUM **") priv_key = self._backend._ffi.new("BIGNUM **") self._backend._lib.DSA_get0_pqg(self._dsa_cdata, p, q, g) self._backend.openssl_assert(p[0] != self._backend._ffi.NULL) self._backend.openssl_assert(q[0] != self._backend._ffi.NULL) self._backend.openssl_assert(g[0] != self._backend._ffi.NULL) self._backend._lib.DSA_get0_key(self._dsa_cdata, pub_key, priv_key) self._backend.openssl_assert(pub_key[0] != self._backend._ffi.NULL) self._backend.openssl_assert(priv_key[0] != self._backend._ffi.NULL) return dsa.DSAPrivateNumbers(public_numbers=dsa.DSAPublicNumbers( parameter_numbers=dsa.DSAParameterNumbers( p=self._backend._bn_to_int(p[0]), q=self._backend._bn_to_int(q[0]), g=self._backend._bn_to_int(g[0])), y=self._backend._bn_to_int(pub_key[0])), x=self._backend._bn_to_int(priv_key[0]))
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 test_dsa_signing(self, vector, backend): digest_algorithm = vector['digest_algorithm'].replace("-", "") algorithm = self._algorithms_dict[digest_algorithm] _skip_if_dsa_not_supported(backend, algorithm, vector['p'], vector['q'], vector['g']) private_key = dsa.DSAPrivateNumbers( public_numbers=dsa.DSAPublicNumbers( parameter_numbers=dsa.DSAParameterNumbers( vector['p'], vector['q'], vector['g']), y=vector['y']), x=vector['x']).private_key(backend) signer = pytest.deprecated_call(private_key.signer, algorithm()) signer.update(vector['msg']) signature = signer.finalize() assert signature public_key = private_key.public_key() verifier = public_key.verifier(signature, algorithm()) verifier.update(vector['msg']) verifier.verify()
def test_dsa_signing(self, vector, backend): digest_algorithm = vector['digest_algorithm'].replace("-", "") algorithm = self._algorithms_dict[digest_algorithm] if (not backend.dsa_parameters_supported(vector['p'], vector['q'], vector['g']) or not backend.dsa_hash_supported(algorithm)): pytest.skip( "{0} does not support the provided parameters".format(backend)) private_key = dsa.DSAPrivateNumbers( public_numbers=dsa.DSAPublicNumbers( parameter_numbers=dsa.DSAParameterNumbers( vector['p'], vector['q'], vector['g']), y=vector['y']), x=vector['x']).private_key(backend) signer = private_key.signer(algorithm()) signer.update(vector['msg']) signature = signer.finalize() assert signature public_key = private_key.public_key() verifier = public_key.verifier(signature, algorithm()) verifier.update(vector['msg']) verifier.verify()
def test_private_numbers_eq(self): pub = dsa.DSAPublicNumbers(1, dsa.DSAParameterNumbers(1, 2, 3)) priv = dsa.DSAPrivateNumbers(1, pub) assert priv == dsa.DSAPrivateNumbers( 1, dsa.DSAPublicNumbers(1, dsa.DSAParameterNumbers(1, 2, 3)))
def test_invalid_dsa_private_key_arguments(self, backend): # Test a p < 1024 bits in length with pytest.raises(ValueError): dsa.DSAPrivateNumbers(public_numbers=dsa.DSAPublicNumbers( parameter_numbers=dsa.DSAParameterNumbers( p=2**1000, q=DSA_KEY_1024.public_numbers.parameter_numbers.q, g=DSA_KEY_1024.public_numbers.parameter_numbers.g, ), y=DSA_KEY_1024.public_numbers.y), x=DSA_KEY_1024.x).private_key(backend) # Test a p < 2048 bits in length with pytest.raises(ValueError): dsa.DSAPrivateNumbers( public_numbers=dsa.DSAPublicNumbers( parameter_numbers=dsa.DSAParameterNumbers( p=2**2000, q=DSA_KEY_2048.public_numbers.parameter_numbers.q, g=DSA_KEY_2048.public_numbers.parameter_numbers.g, ), y=DSA_KEY_2048.public_numbers.y), x=DSA_KEY_2048.x, ).private_key(backend) # Test a p < 3072 bits in length with pytest.raises(ValueError): dsa.DSAPrivateNumbers( public_numbers=dsa.DSAPublicNumbers( parameter_numbers=dsa.DSAParameterNumbers( p=2**3000, q=DSA_KEY_3072.public_numbers.parameter_numbers.q, g=DSA_KEY_3072.public_numbers.parameter_numbers.g, ), y=DSA_KEY_3072.public_numbers.y), x=DSA_KEY_3072.x, ).private_key(backend) # Test a p > 3072 bits in length with pytest.raises(ValueError): dsa.DSAPrivateNumbers( public_numbers=dsa.DSAPublicNumbers( parameter_numbers=dsa.DSAParameterNumbers( p=2**3100, q=DSA_KEY_3072.public_numbers.parameter_numbers.q, g=DSA_KEY_3072.public_numbers.parameter_numbers.g, ), y=DSA_KEY_3072.public_numbers.y), x=DSA_KEY_3072.x, ).private_key(backend) # Test a q < 160 bits in length with pytest.raises(ValueError): dsa.DSAPrivateNumbers( public_numbers=dsa.DSAPublicNumbers( parameter_numbers=dsa.DSAParameterNumbers( p=DSA_KEY_1024.public_numbers.parameter_numbers.p, q=2**150, g=DSA_KEY_1024.public_numbers.parameter_numbers.g, ), y=DSA_KEY_1024.public_numbers.y), x=DSA_KEY_1024.x, ).private_key(backend) # Test a q < 256 bits in length with pytest.raises(ValueError): dsa.DSAPrivateNumbers( public_numbers=dsa.DSAPublicNumbers( parameter_numbers=dsa.DSAParameterNumbers( p=DSA_KEY_2048.public_numbers.parameter_numbers.p, q=2**250, g=DSA_KEY_2048.public_numbers.parameter_numbers.g, ), y=DSA_KEY_2048.public_numbers.y), x=DSA_KEY_2048.x, ).private_key(backend) # Test a q > 256 bits in length with pytest.raises(ValueError): dsa.DSAPrivateNumbers( public_numbers=dsa.DSAPublicNumbers( parameter_numbers=dsa.DSAParameterNumbers( p=DSA_KEY_3072.public_numbers.parameter_numbers.p, q=2**260, g=DSA_KEY_3072.public_numbers.parameter_numbers.g, ), y=DSA_KEY_3072.public_numbers.y), x=DSA_KEY_3072.x, ).private_key(backend) # Test a g < 1 with pytest.raises(ValueError): dsa.DSAPrivateNumbers( public_numbers=dsa.DSAPublicNumbers( parameter_numbers=dsa.DSAParameterNumbers( p=DSA_KEY_1024.public_numbers.parameter_numbers.p, q=DSA_KEY_1024.public_numbers.parameter_numbers.q, g=0, ), y=DSA_KEY_1024.public_numbers.y), x=DSA_KEY_1024.x, ).private_key(backend) # Test a g = 1 with pytest.raises(ValueError): dsa.DSAPrivateNumbers( public_numbers=dsa.DSAPublicNumbers( parameter_numbers=dsa.DSAParameterNumbers( p=DSA_KEY_1024.public_numbers.parameter_numbers.p, q=DSA_KEY_1024.public_numbers.parameter_numbers.q, g=1, ), y=DSA_KEY_1024.public_numbers.y), x=DSA_KEY_1024.x, ).private_key(backend) # Test a g > p with pytest.raises(ValueError): dsa.DSAPrivateNumbers( public_numbers=dsa.DSAPublicNumbers( parameter_numbers=dsa.DSAParameterNumbers( p=DSA_KEY_1024.public_numbers.parameter_numbers.p, q=DSA_KEY_1024.public_numbers.parameter_numbers.q, g=2**1200, ), y=DSA_KEY_1024.public_numbers.y), x=DSA_KEY_1024.x, ).private_key(backend) # Test x = 0 with pytest.raises(ValueError): dsa.DSAPrivateNumbers( public_numbers=dsa.DSAPublicNumbers( parameter_numbers=dsa.DSAParameterNumbers( p=DSA_KEY_1024.public_numbers.parameter_numbers.p, q=DSA_KEY_1024.public_numbers.parameter_numbers.q, g=DSA_KEY_1024.public_numbers.parameter_numbers.g, ), y=DSA_KEY_1024.public_numbers.y), x=0, ).private_key(backend) # Test x < 0 with pytest.raises(ValueError): dsa.DSAPrivateNumbers( public_numbers=dsa.DSAPublicNumbers( parameter_numbers=dsa.DSAParameterNumbers( p=DSA_KEY_1024.public_numbers.parameter_numbers.p, q=DSA_KEY_1024.public_numbers.parameter_numbers.q, g=DSA_KEY_1024.public_numbers.parameter_numbers.g, ), y=DSA_KEY_1024.public_numbers.y), x=-2, ).private_key(backend) # Test x = q with pytest.raises(ValueError): dsa.DSAPrivateNumbers( public_numbers=dsa.DSAPublicNumbers( parameter_numbers=dsa.DSAParameterNumbers( p=DSA_KEY_1024.public_numbers.parameter_numbers.p, q=DSA_KEY_1024.public_numbers.parameter_numbers.q, g=DSA_KEY_1024.public_numbers.parameter_numbers.g, ), y=DSA_KEY_1024.public_numbers.y), x=2**159, ).private_key(backend) # Test x > q with pytest.raises(ValueError): dsa.DSAPrivateNumbers( public_numbers=dsa.DSAPublicNumbers( parameter_numbers=dsa.DSAParameterNumbers( p=DSA_KEY_1024.public_numbers.parameter_numbers.p, q=DSA_KEY_1024.public_numbers.parameter_numbers.q, g=DSA_KEY_1024.public_numbers.parameter_numbers.g, ), y=DSA_KEY_1024.public_numbers.y), x=2**200, ).private_key(backend) # Test y != (g ** x) % p with pytest.raises(ValueError): dsa.DSAPrivateNumbers( public_numbers=dsa.DSAPublicNumbers( parameter_numbers=dsa.DSAParameterNumbers( p=DSA_KEY_1024.public_numbers.parameter_numbers.p, q=DSA_KEY_1024.public_numbers.parameter_numbers.q, g=DSA_KEY_1024.public_numbers.parameter_numbers.g, ), y=2**100), x=DSA_KEY_1024.x, ).private_key(backend) # Test a non-integer y value with pytest.raises(TypeError): dsa.DSAPrivateNumbers( public_numbers=dsa.DSAPublicNumbers( parameter_numbers=dsa.DSAParameterNumbers( p=DSA_KEY_1024.public_numbers.parameter_numbers.p, q=DSA_KEY_1024.public_numbers.parameter_numbers.q, g=DSA_KEY_1024.public_numbers.parameter_numbers.g, ), y=None), x=DSA_KEY_1024.x, ).private_key(backend) # Test a non-integer x value with pytest.raises(TypeError): dsa.DSAPrivateNumbers( public_numbers=dsa.DSAPublicNumbers( parameter_numbers=dsa.DSAParameterNumbers( p=DSA_KEY_1024.public_numbers.parameter_numbers.p, q=DSA_KEY_1024.public_numbers.parameter_numbers.q, g=DSA_KEY_1024.public_numbers.parameter_numbers.g, ), y=DSA_KEY_1024.public_numbers.y), x=None, ).private_key(backend)
def construct_key(*, p, q, g, y, x) -> dsa.DSAPrivateKey: params = dsa.DSAParameterNumbers(p, q, g) pub = dsa.DSAPublicNumbers(y, params) priv = dsa.DSAPrivateNumbers(x, pub) return priv.private_key(backend=default_backend())
def _fromString_PRIVATE_OPENSSH(cls, data, passphrase): """ Return a private key object corresponding to this OpenSSH private key string. If the key is encrypted, passphrase MUST be provided. Providing a passphrase for an unencrypted key is an error. The format of an OpenSSH private key string is:: -----BEGIN <key type> PRIVATE KEY----- [Proc-Type: 4,ENCRYPTED DEK-Info: DES-EDE3-CBC,<initialization value>] <base64-encoded ASN.1 structure> ------END <key type> PRIVATE KEY------ The ASN.1 structure of a RSA key is:: (0, n, e, d, p, q) The ASN.1 structure of a DSA key is:: (0, p, q, g, y, x) The ASN.1 structure of a ECDSA key is:: (ECParameters, OID, NULL) @type data: L{bytes} @param data: The key data. @type passphrase: L{bytes} or L{None} @param passphrase: The passphrase the key is encrypted with, or L{None} if it is not encrypted. @return: A new key. @rtype: L{twisted.conch.ssh.keys.Key} @raises BadKeyError: if * a passphrase is provided for an unencrypted key * the ASN.1 encoding is incorrect @raises EncryptedKeyError: if * a passphrase is not provided for an encrypted key """ lines = data.strip().splitlines() kind = lines[0][11:-17] if lines[1].startswith(b'Proc-Type: 4,ENCRYPTED'): if not passphrase: raise EncryptedKeyError('Passphrase must be provided ' 'for an encrypted key') # Determine cipher and initialization vector try: _, cipherIVInfo = lines[2].split(b' ', 1) cipher, ivdata = cipherIVInfo.rstrip().split(b',', 1) except ValueError: raise BadKeyError('invalid DEK-info %r' % (lines[2],)) if cipher in (b'AES-128-CBC', b'AES-256-CBC'): algorithmClass = algorithms.AES keySize = int(int(cipher.split(b'-')[1])/8) if len(ivdata) != 32: raise BadKeyError('AES encrypted key with a bad IV') elif cipher == b'DES-EDE3-CBC': algorithmClass = algorithms.TripleDES keySize = 24 if len(ivdata) != 16: raise BadKeyError('DES encrypted key with a bad IV') else: raise BadKeyError('unknown encryption type %r' % (cipher,)) # Extract keyData for decoding iv = bytes(bytearray([int(ivdata[i:i + 2], 16) for i in range(0, len(ivdata), 2)])) ba = md5(passphrase + iv[:8]).digest() bb = md5(ba + passphrase + iv[:8]).digest() decKey = (ba + bb)[:keySize] b64Data = decodebytes(b''.join(lines[3:-1])) decryptor = Cipher( algorithmClass(decKey), modes.CBC(iv), backend=default_backend() ).decryptor() keyData = decryptor.update(b64Data) + decryptor.finalize() removeLen = ord(keyData[-1:]) keyData = keyData[:-removeLen] else: b64Data = b''.join(lines[1:-1]) keyData = decodebytes(b64Data) try: decodedKey = berDecoder.decode(keyData)[0] except PyAsn1Error as e: raise BadKeyError( 'Failed to decode key (Bad Passphrase?): %s' % (e,)) if kind == b'EC': return cls( load_pem_private_key(data, passphrase, default_backend())) if kind == b'RSA': if len(decodedKey) == 2: # Alternate RSA key decodedKey = decodedKey[0] if len(decodedKey) < 6: raise BadKeyError('RSA key failed to decode properly') n, e, d, p, q, dmp1, dmq1, iqmp = [ long(value) for value in decodedKey[1:9] ] if p > q: # Make p smaller than q p, q = q, p return cls( rsa.RSAPrivateNumbers( p=p, q=q, d=d, dmp1=dmp1, dmq1=dmq1, iqmp=iqmp, public_numbers=rsa.RSAPublicNumbers(e=e, n=n), ).private_key(default_backend()) ) elif kind == b'DSA': p, q, g, y, x = [long(value) for value in decodedKey[1: 6]] if len(decodedKey) < 6: raise BadKeyError('DSA key failed to decode properly') return cls( dsa.DSAPrivateNumbers( x=x, public_numbers=dsa.DSAPublicNumbers( y=y, parameter_numbers=dsa.DSAParameterNumbers( p=p, q=q, g=g ) ) ).private_key(backend=default_backend()) ) else: raise BadKeyError("unknown key type %s" % (kind,))
def __privkey__(self): params = dsa.DSAParameterNumbers(self.p, self.q, self.g) pn = dsa.DSAPublicNumbers(self.y, params) return dsa.DSAPrivateNumbers(self.x, pn).private_key(default_backend())
def test_invalid_dsa_private_key_arguments(self, p, q, g, y, x, backend): with pytest.raises(ValueError): dsa.DSAPrivateNumbers(public_numbers=dsa.DSAPublicNumbers( parameter_numbers=dsa.DSAParameterNumbers(p=p, q=q, g=g), y=y), x=x).private_key(backend)