| 1 | # -*- test-case-name: twisted.conch.test.test_ssh -*- |
|---|
| 2 | # Copyright (c) Twisted Matrix Laboratories. |
|---|
| 3 | # See LICENSE for details. |
|---|
| 4 | |
|---|
| 5 | |
|---|
| 6 | """ |
|---|
| 7 | Common functions for the SSH classes. |
|---|
| 8 | |
|---|
| 9 | Maintainer: Paul Swartz |
|---|
| 10 | """ |
|---|
| 11 | |
|---|
| 12 | import struct, warnings |
|---|
| 13 | |
|---|
| 14 | try: |
|---|
| 15 | from Crypto import Util |
|---|
| 16 | except ImportError: |
|---|
| 17 | warnings.warn("PyCrypto not installed, but continuing anyways!", |
|---|
| 18 | RuntimeWarning) |
|---|
| 19 | |
|---|
| 20 | from twisted.python import randbytes |
|---|
| 21 | |
|---|
| 22 | |
|---|
| 23 | def NS(t): |
|---|
| 24 | """ |
|---|
| 25 | net string |
|---|
| 26 | """ |
|---|
| 27 | return struct.pack('!L',len(t)) + t |
|---|
| 28 | |
|---|
| 29 | def getNS(s, count=1): |
|---|
| 30 | """ |
|---|
| 31 | get net string |
|---|
| 32 | """ |
|---|
| 33 | ns = [] |
|---|
| 34 | c = 0 |
|---|
| 35 | for i in range(count): |
|---|
| 36 | l, = struct.unpack('!L',s[c:c+4]) |
|---|
| 37 | ns.append(s[c+4:4+l+c]) |
|---|
| 38 | c += 4 + l |
|---|
| 39 | return tuple(ns) + (s[c:],) |
|---|
| 40 | |
|---|
| 41 | def MP(number): |
|---|
| 42 | if number==0: return '\000'*4 |
|---|
| 43 | assert number>0 |
|---|
| 44 | bn = Util.number.long_to_bytes(number) |
|---|
| 45 | if ord(bn[0])&128: |
|---|
| 46 | bn = '\000' + bn |
|---|
| 47 | return struct.pack('>L',len(bn)) + bn |
|---|
| 48 | |
|---|
| 49 | def getMP(data, count=1): |
|---|
| 50 | """ |
|---|
| 51 | Get multiple precision integer out of the string. A multiple precision |
|---|
| 52 | integer is stored as a 4-byte length followed by length bytes of the |
|---|
| 53 | integer. If count is specified, get count integers out of the string. |
|---|
| 54 | The return value is a tuple of count integers followed by the rest of |
|---|
| 55 | the data. |
|---|
| 56 | """ |
|---|
| 57 | mp = [] |
|---|
| 58 | c = 0 |
|---|
| 59 | for i in range(count): |
|---|
| 60 | length, = struct.unpack('>L',data[c:c+4]) |
|---|
| 61 | mp.append(Util.number.bytes_to_long(data[c+4:c+4+length])) |
|---|
| 62 | c += 4 + length |
|---|
| 63 | return tuple(mp) + (data[c:],) |
|---|
| 64 | |
|---|
| 65 | def _MPpow(x, y, z): |
|---|
| 66 | """return the MP version of (x**y)%z |
|---|
| 67 | """ |
|---|
| 68 | return MP(pow(x,y,z)) |
|---|
| 69 | |
|---|
| 70 | def ffs(c, s): |
|---|
| 71 | """ |
|---|
| 72 | first from second |
|---|
| 73 | goes through the first list, looking for items in the second, returns the first one |
|---|
| 74 | """ |
|---|
| 75 | for i in c: |
|---|
| 76 | if i in s: return i |
|---|
| 77 | |
|---|
| 78 | getMP_py = getMP |
|---|
| 79 | MP_py = MP |
|---|
| 80 | _MPpow_py = _MPpow |
|---|
| 81 | pyPow = pow |
|---|
| 82 | |
|---|
| 83 | def _fastgetMP(data, count=1): |
|---|
| 84 | mp = [] |
|---|
| 85 | c = 0 |
|---|
| 86 | for i in range(count): |
|---|
| 87 | length = struct.unpack('!L', data[c:c+4])[0] |
|---|
| 88 | mp.append(long(gmpy.mpz(data[c + 4:c + 4 + length][::-1] + '\x00', 256))) |
|---|
| 89 | c += length + 4 |
|---|
| 90 | return tuple(mp) + (data[c:],) |
|---|
| 91 | |
|---|
| 92 | def _fastMP(i): |
|---|
| 93 | i2 = gmpy.mpz(i).binary()[::-1] |
|---|
| 94 | return struct.pack('!L', len(i2)) + i2 |
|---|
| 95 | |
|---|
| 96 | def _fastMPpow(x, y, z=None): |
|---|
| 97 | r = pyPow(gmpy.mpz(x),y,z).binary()[::-1] |
|---|
| 98 | return struct.pack('!L', len(r)) + r |
|---|
| 99 | |
|---|
| 100 | def install(): |
|---|
| 101 | global getMP, MP, _MPpow |
|---|
| 102 | getMP = _fastgetMP |
|---|
| 103 | MP = _fastMP |
|---|
| 104 | _MPpow = _fastMPpow |
|---|
| 105 | # XXX: We override builtin pow so that PyCrypto can benefit from gmpy too. |
|---|
| 106 | def _fastpow(x, y, z=None, mpz=gmpy.mpz): |
|---|
| 107 | if type(x) in (long, int): |
|---|
| 108 | x = mpz(x) |
|---|
| 109 | return pyPow(x, y, z) |
|---|
| 110 | __builtins__['pow'] = _fastpow # evil evil |
|---|
| 111 | |
|---|
| 112 | try: |
|---|
| 113 | import gmpy |
|---|
| 114 | install() |
|---|
| 115 | except ImportError: |
|---|
| 116 | pass |
|---|