python - 在 Python 中使用 paramiko 生成 SSH key 对

标签 python python-2.7 paramiko

我正在尝试使用 python 模块 paramiko 生成 SSH key 对。似乎没有太多关于 key 生成的信息。我已经通读了 paramiko 文档,但无法弄清楚出了什么问题。我可以生成没有密码加密的私钥和公钥。但是,当我尝试加密私钥时,出现以下错误。

ValueError:IV 的长度必须为 8 个字节

我相信上述错误来自 pycrypto。我已经查看了 paramiko.pkey 和 pycrypto 中的相关代码,但没有任何运气。

这是一个小例子。

import paramiko

def keygen(filename,passwd=None,bits=1024):
    k = paramiko.RSAKey.generate(bits)
    #This line throws the error.
    k.write_private_key_file(filename,password = 'cleverpassword')
    o = open(fil+'.pub' ,"w").write(k.get_base64())

回溯

Traceback (most recent call last):
  File "/var/mobile/Applications/149E4C21-2F92-4712-BAC6-151A171C6687/Documents/test.py", line 14, in keygen
    k.write_private_key_file(filename,password = 'cleverpassword')
  File "/var/mobile/Applications/149E4C21-2F92-4712-BAC6-151A171C6687/Pythonista.app/pylib/site-packages/paramiko/rsakey.py", line 127, in write_private_key_file
    self._write_private_key_file('RSA', filename, self._encode_key(), password)
  File "/var/mobile/Applications/149E4C21-2F92-4712-BAC6-151A171C6687/Pythonista.app/pylib/site-packages/paramiko/pkey.py", line 323, in _write_private_key_file
    self._write_private_key(tag, f, data, password)
  File "/var/mobile/Applications/149E4C21-2F92-4712-BAC6-151A171C6687/Pythonista.app/pylib/site-packages/paramiko/pkey.py", line 341, in _write_private_key
    data = cipher.new(key, mode, salt).encrypt(data)
  File "/var/mobile/Applications/149E4C21-2F92-4712-BAC6-151A171C6687/Pythonista.app/pylib/site-packages/Crypto/Cipher/DES3.py", line 114, in new
    return DES3Cipher(key, *args, **kwargs)
  File "/var/mobile/Applications/149E4C21-2F92-4712-BAC6-151A171C6687/Pythonista.app/pylib/site-packages/Crypto/Cipher/DES3.py", line 76, in __init__
    blockalgo.BlockAlgo.__init__(self, _DES3, key, *args, **kwargs)
  File "/var/mobile/Applications/149E4C21-2F92-4712-BAC6-151A171C6687/Pythonista.app/pylib/site-packages/Crypto/Cipher/blockalgo.py", line 141, in __init__
    self._cipher = factory.new(key, *args, **kwargs)
ValueError: IV must be 8 bytes long

最佳答案

问题

这看起来像是 paramiko 中的错误。

如果您查看 pkey.py 中引发错误的行,它是以下行:

        data = cipher.new(key, mode, salt).encrypt(data)

现在让我们看看它之前的几行,它通过首先选择一个 cipher_name 来设置 mode

        # 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']

这里是_CIPHER_TABLE的内容。

_CIPHER_TABLE = {
    'AES-128-CBC': {'cipher': AES, 'keysize': 16, 'blocksize': 16, 'mode': AES.MODE_CBC},
    'DES-EDE3-CBC': {'cipher': DES3, 'keysize': 24, 'blocksize': 8, 'mode': DES3.MODE_CBC},
}

观察注释如何与代码相矛盾。有两个密码可用,上面选择 cipher_name 的行假设只有一个。

根据错误,似乎选择了 'DES-EDE3-CBC'。如果我们查看 DES3.py 中的注释,我们会看到以下对 IV 的要求。

  IV : byte string
    The initialization vector to use for encryption or decryption.

    It is ignored for `MODE_ECB` and `MODE_CTR`.

    For `MODE_OPENPGP`, IV must be `block_size` bytes long for encryption
    and `block_size` +2 bytes for decryption (in the latter case, it is
    actually the *encrypted* IV which was prefixed to the ciphertext).
    It is mandatory.

从 paramiko 的来源,我们观察到没有 IV 被传递,因此我们看到了错误。

解决方法

更改 pkey.py 中的以下行以硬编码 'AES-128-CBC' 密码。

   # cipher_name = list(self._CIPHER_TABLE.keys())[1]
   cipher_name = 'AES-128-CBC'

关于python - 在 Python 中使用 paramiko 生成 SSH key 对,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24463500/

相关文章:

python paramiko ssh

python - .one() 和 .first() 有什么区别

python - Spark 流作业性能改进

python - 使用python在cmd中传递变量

python - 为时代换弦

python - 无法使用 Python Paramiko 执行带有重定向多行输入的 shell 命令

python - Web框架的局限性如何

python - 列出网站上的所有文件

python覆盖上一行

python - 如何使用 sudo 启动 Python Paramiko SFTP?