Team Ai
Datasetpublic

codekingpro/portable-devtools

sourceHugging Faceupdated 5mo agoView on Hugging Face
1likes14kdownloads
dsskey.py259 linesDownload Raw Back to paramiko
1# Copyright (C) 2003-2007  Robey Pointer <robeypointer@gmail.com>2#3# This file is part of paramiko.4#5# Paramiko is free software; you can redistribute it and/or modify it under the6# terms of the GNU Lesser General Public License as published by the Free7# Software Foundation; either version 2.1 of the License, or (at your option)8# any later version.9#10# Paramiko is distributed in the hope that it will be useful, but WITHOUT ANY11# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR12# A PARTICULAR PURPOSE.  See the GNU Lesser General Public License for more13# details.14#15# You should have received a copy of the GNU Lesser General Public License16# along with Paramiko; if not, write to the Free Software Foundation, Inc.,17# 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301 USA.18 19"""20DSS keys.21"""22 23from cryptography.exceptions import InvalidSignature24from cryptography.hazmat.backends import default_backend25from cryptography.hazmat.primitives import hashes, serialization26from cryptography.hazmat.primitives.asymmetric import dsa27from cryptography.hazmat.primitives.asymmetric.utils import (28    decode_dss_signature,29    encode_dss_signature,30)31 32from paramiko import util33from paramiko.common import zero_byte34from paramiko.ssh_exception import SSHException35from paramiko.message import Message36from paramiko.ber import BER, BERException37from paramiko.pkey import PKey38 39 40class DSSKey(PKey):41    """42    Representation of a DSS key which can be used to sign an verify SSH243    data.44    """45 46    name = "ssh-dss"47 48    def __init__(49        self,50        msg=None,51        data=None,52        filename=None,53        password=None,54        vals=None,55        file_obj=None,56    ):57        self.p = None58        self.q = None59        self.g = None60        self.y = None61        self.x = None62        self.public_blob = None63        if file_obj is not None:64            self._from_private_key(file_obj, password)65            return66        if filename is not None:67            self._from_private_key_file(filename, password)68            return69        if (msg is None) and (data is not None):70            msg = Message(data)71        if vals is not None:72            self.p, self.q, self.g, self.y = vals73        else:74            self._check_type_and_load_cert(75                msg=msg,76                key_type=self.name,77                cert_type=f"{self.name}-cert-v01@openssh.com",78            )79            self.p = msg.get_mpint()80            self.q = msg.get_mpint()81            self.g = msg.get_mpint()82            self.y = msg.get_mpint()83        self.size = util.bit_length(self.p)84 85    def asbytes(self):86        m = Message()87        m.add_string(self.name)88        m.add_mpint(self.p)89        m.add_mpint(self.q)90        m.add_mpint(self.g)91        m.add_mpint(self.y)92        return m.asbytes()93 94    def __str__(self):95        return self.asbytes()96 97    @property98    def _fields(self):99        return (self.get_name(), self.p, self.q, self.g, self.y)100 101    # TODO 4.0: remove102    def get_name(self):103        return self.name104 105    def get_bits(self):106        return self.size107 108    def can_sign(self):109        return self.x is not None110 111    def sign_ssh_data(self, data, algorithm=None):112        key = dsa.DSAPrivateNumbers(113            x=self.x,114            public_numbers=dsa.DSAPublicNumbers(115                y=self.y,116                parameter_numbers=dsa.DSAParameterNumbers(117                    p=self.p, q=self.q, g=self.g118                ),119            ),120        ).private_key(backend=default_backend())121        sig = key.sign(data, hashes.SHA1())122        r, s = decode_dss_signature(sig)123 124        m = Message()125        m.add_string(self.name)126        # apparently, in rare cases, r or s may be shorter than 20 bytes!127        rstr = util.deflate_long(r, 0)128        sstr = util.deflate_long(s, 0)129        if len(rstr) < 20:130            rstr = zero_byte * (20 - len(rstr)) + rstr131        if len(sstr) < 20:132            sstr = zero_byte * (20 - len(sstr)) + sstr133        m.add_string(rstr + sstr)134        return m135 136    def verify_ssh_sig(self, data, msg):137        if len(msg.asbytes()) == 40:138            # spies.com bug: signature has no header139            sig = msg.asbytes()140        else:141            kind = msg.get_text()142            if kind != self.name:143                return 0144            sig = msg.get_binary()145 146        # pull out (r, s) which are NOT encoded as mpints147        sigR = util.inflate_long(sig[:20], 1)148        sigS = util.inflate_long(sig[20:], 1)149 150        signature = encode_dss_signature(sigR, sigS)151 152        key = dsa.DSAPublicNumbers(153            y=self.y,154            parameter_numbers=dsa.DSAParameterNumbers(155                p=self.p, q=self.q, g=self.g156            ),157        ).public_key(backend=default_backend())158        try:159            key.verify(signature, data, hashes.SHA1())160        except InvalidSignature:161            return False162        else:163            return True164 165    def write_private_key_file(self, filename, password=None):166        key = dsa.DSAPrivateNumbers(167            x=self.x,168            public_numbers=dsa.DSAPublicNumbers(169                y=self.y,170                parameter_numbers=dsa.DSAParameterNumbers(171                    p=self.p, q=self.q, g=self.g172                ),173            ),174        ).private_key(backend=default_backend())175 176        self._write_private_key_file(177            filename,178            key,179            serialization.PrivateFormat.TraditionalOpenSSL,180            password=password,181        )182 183    def write_private_key(self, file_obj, password=None):184        key = dsa.DSAPrivateNumbers(185            x=self.x,186            public_numbers=dsa.DSAPublicNumbers(187                y=self.y,188                parameter_numbers=dsa.DSAParameterNumbers(189                    p=self.p, q=self.q, g=self.g190                ),191            ),192        ).private_key(backend=default_backend())193 194        self._write_private_key(195            file_obj,196            key,197            serialization.PrivateFormat.TraditionalOpenSSL,198            password=password,199        )200 201    @staticmethod202    def generate(bits=1024, progress_func=None):203        """204        Generate a new private DSS key.  This factory function can be used to205        generate a new host key or authentication key.206 207        :param int bits: number of bits the generated key should be.208        :param progress_func: Unused209        :return: new `.DSSKey` private key210        """211        numbers = dsa.generate_private_key(212            bits, backend=default_backend()213        ).private_numbers()214        key = DSSKey(215            vals=(216                numbers.public_numbers.parameter_numbers.p,217                numbers.public_numbers.parameter_numbers.q,218                numbers.public_numbers.parameter_numbers.g,219                numbers.public_numbers.y,220            )221        )222        key.x = numbers.x223        return key224 225    # ...internals...226 227    def _from_private_key_file(self, filename, password):228        data = self._read_private_key_file("DSA", filename, password)229        self._decode_key(data)230 231    def _from_private_key(self, file_obj, password):232        data = self._read_private_key("DSA", file_obj, password)233        self._decode_key(data)234 235    def _decode_key(self, data):236        pkformat, data = data237        # private key file contains:238        # DSAPrivateKey = { version = 0, p, q, g, y, x }239        if pkformat == self._PRIVATE_KEY_FORMAT_ORIGINAL:240            try:241                keylist = BER(data).decode()242            except BERException as e:243                raise SSHException("Unable to parse key file: {}".format(e))244        elif pkformat == self._PRIVATE_KEY_FORMAT_OPENSSH:245            keylist = self._uint32_cstruct_unpack(data, "iiiii")246            keylist = [0] + list(keylist)247        else:248            self._got_bad_key_format_id(pkformat)249        if type(keylist) is not list or len(keylist) < 6 or keylist[0] != 0:250            raise SSHException(251                "not a valid DSA private key file (bad ber encoding)"252            )253        self.p = keylist[1]254        self.q = keylist[2]255        self.g = keylist[3]256        self.y = keylist[4]257        self.x = keylist[5]258        self.size = util.bit_length(self.p)259 
codekingpro/portable-devtools · Team Ai