Sign Up
Log In
Log In
or
Sign Up
Places
All Projects
Status Monitor
Collapse sidebar
DISCONTINUED:openSUSE:11.2
python-twisted
Twisted-8.2.0-deprecations.patch
Overview
Repositories
Revisions
Requests
Users
Attributes
Meta
File Twisted-8.2.0-deprecations.patch of Package python-twisted
--- twisted/conch/scripts/ckeygen.py +++ twisted/conch/scripts/ckeygen.py @@ -1,16 +1,12 @@ -# Copyright (c) 2001-2007 Twisted Matrix Laboratories. +# -*- test-case-name: twisted.conch.test.test_ckeygen -*- +# Copyright (c) 2001-2008 Twisted Matrix Laboratories. # See LICENSE for details. -# -# $Id: ckeygen.py,v 1.8 2003/05/10 14:03:40 spiv Exp $ +""" +Implementation module for the `ckeygen` command. +""" -#""" Implementation module for the `ckeygen` command. -#""" - -from twisted.conch.ssh import keys -from twisted.python import log, usage, randbytes - -import sys, os, getpass, md5, socket +import sys, os, getpass, socket if getpass.getpass == getpass.unix_getpass: try: import termios # hack around broken termios @@ -19,6 +15,10 @@ sys.modules['termios'] = None reload(getpass) +from twisted.conch.ssh import keys +from twisted.python import filepath, log, usage, randbytes + + class GeneralOptions(usage.Options): synopsis = """Usage: ckeygen [options] """ @@ -88,6 +88,7 @@ key = DSA.generate(int(options['bits']), randbytes.secureRandom) _saveKey(key, options) + def printFingerprint(options): if not options['filename']: filename = os.path.expanduser('~/.ssh/id_rsa') @@ -95,11 +96,12 @@ if os.path.exists(options['filename']+'.pub'): options['filename'] += '.pub' try: - string = keys.getPublicKeyString(options['filename']) - obj = keys.getPublicKeyObject(string) + key = keys.Key.fromFile(options['filename']) + obj = key.keyObject + string = key.blob() print '%s %s %s' % ( - obj.size()+1, - ':'.join(['%02x' % ord(x) for x in md5.new(string).digest()]), + obj.size() + 1, + key.fingerprint(), os.path.basename(options['filename'])) except: sys.exit('bad key') @@ -163,17 +165,21 @@ break print 'Passphrases do not match. Try again.' options['pass'] = p1 + + keyObj = keys.Key(key) comment = '%s@%s' % (getpass.getuser(), socket.gethostname()) - open(options['filename'], 'w').write( - keys.makePrivateKeyString(key, passphrase=options['pass'])) + + filepath.FilePath(options['filename']).setContent( + keyObj.toString('openssh', options['pass'])) os.chmod(options['filename'], 33152) - open(options['filename']+'.pub', 'w').write( - keys.makePublicKeyString(key, comment = comment)) - pubKey = keys.getPublicKeyString(data=keys.makePublicKeyString(key, comment=comment)) + + filepath.FilePath(options['filename'] + '.pub').setContent( + keyObj.public().toString('openssh', comment)) + print 'Your identification has been saved in %s' % options['filename'] print 'Your public key has been saved in %s.pub' % options['filename'] print 'The key fingerprint is:' - print ':'.join(['%02x' % ord(x) for x in md5.new(pubKey).digest()]) + print keyObj.fingerprint() if __name__ == '__main__': run() --- twisted/conch/ssh/keys.py +++ twisted/conch/ssh/keys.py @@ -10,7 +10,6 @@ # base library imports import base64 -import sha, md5 import warnings # external library imports @@ -20,6 +19,7 @@ # twisted from twisted.python import randbytes +from twisted.python.hashlib import md5, sha1 # sibling imports from twisted.conch.ssh import asn1, common, sexpy @@ -205,8 +205,8 @@ len(ivdata), 2)]) if not passphrase: raise EncryptedKeyError('encrypted key with no passphrase') - ba = md5.new(passphrase + iv).digest() - bb = md5.new(ba + passphrase + iv).digest() + ba = md5(passphrase + iv).digest() + bb = md5(ba + passphrase + iv).digest() decKey = (ba + bb)[:24] b64Data = base64.decodestring(''.join(lines[3:-1])) keyData = DES3.new(decKey, DES3.MODE_CBC, iv).decrypt(b64Data) @@ -443,7 +443,7 @@ @rtype: L{str} """ - return ':'.join([x.encode('hex') for x in md5.md5(self.blob()).digest()]) + return ':'.join([x.encode('hex') for x in md5(self.blob()).digest()]) def type(self): @@ -597,8 +597,8 @@ hexiv = ''.join(['%02X' % ord(x) for x in iv]) lines.append('Proc-Type: 4,ENCRYPTED') lines.append('DEK-Info: DES-EDE3-CBC,%s\n' % hexiv) - ba = md5.new(extra + iv).digest() - bb = md5.new(ba + extra + iv).digest() + ba = md5(extra + iv).digest() + bb = md5(ba + extra + iv).digest() encKey = (ba + bb)[:24] asn1Data = asn1.pack([objData]) if extra: @@ -681,7 +681,7 @@ signature = self.keyObject.sign(digest, '')[0] ret = common.NS(Util.number.long_to_bytes(signature)) elif self.type() == 'DSA': - digest = sha.new(data).digest() + digest = sha1(data).digest() randomBytes = randbytes.secureRandom(19) sig = self.keyObject.sign(digest, randomBytes) # SSH insists that the DSS signature blob be two 160-bit integers @@ -710,7 +710,7 @@ signature = common.getNS(signature)[0] numbers = [Util.number.bytes_to_long(n) for n in signature[:20], signature[20:]] - digest = sha.new(data).digest() + digest = sha1(data).digest() return self.keyObject.verify(digest, numbers) def getPublicKeyString(filename=None, line=0, data=''): @@ -863,7 +863,7 @@ @type data: C{str} @type messageLength: C{str} """ - digest = sha.new(data).digest() + digest = sha1(data).digest() return pkcs1Pad(ID_SHA1+digest, messageLength) def lenSig(obj): --- twisted/conch/ssh/transport.py +++ twisted/conch/ssh/transport.py @@ -13,8 +13,6 @@ # base library imports import struct -import md5 -import sha import zlib import array @@ -26,6 +24,7 @@ from twisted.internet import protocol, defer from twisted.conch import error from twisted.python import log, randbytes +from twisted.python.hashlib import md5, sha1 # sibling imports from twisted.conch.ssh import keys @@ -532,9 +531,9 @@ @type sharedSecret: C{str} @type exchangeHash: C{str} """ - k1 = sha.new(sharedSecret + exchangeHash + c + self.sessionID) + k1 = sha1(sharedSecret + exchangeHash + c + self.sessionID) k1 = k1.digest() - k2 = sha.new(sharedSecret + exchangeHash + k1).digest() + k2 = sha1(sharedSecret + exchangeHash + k1).digest() return k1 + k2 @@ -723,7 +722,7 @@ y = Util.number.getRandomNumber(512, randbytes.secureRandom) serverDHpublicKey = _MPpow(DH_GENERATOR, y, DH_PRIME) sharedSecret = _MPpow(clientDHpublicKey, y, DH_PRIME) - h = sha.new() + h = sha1() h.update(NS(self.otherVersionString)) h.update(NS(self.ourVersionString)) h.update(NS(self.otherKexInitPayload)) @@ -792,7 +791,7 @@ serverDHpublicKey = _MPpow(self.g, y, self.p) sharedSecret = _MPpow(clientDHpublicKey, y, self.p) - h = sha.new() + h = sha1() h.update(NS(self.otherVersionString)) h.update(NS(self.ourVersionString)) h.update(NS(self.otherKexInitPayload)) @@ -933,7 +932,7 @@ f, packet = getMP(packet) signature, packet = getNS(packet) fingerprint = ':'.join([ch.encode('hex') for ch in - md5.new(pubKey).digest()]) + md5(pubKey).digest()]) d = self.verifyHostKey(pubKey, fingerprint) d.addCallback(self._continueKEXDH_REPLY, pubKey, f, signature) d.addErrback( @@ -962,7 +961,7 @@ """ serverKey = keys.Key.fromString(pubKey) sharedSecret = _MPpow(f, self.x, DH_PRIME) - h = sha.new() + h = sha1() h.update(NS(self.ourVersionString)) h.update(NS(self.otherVersionString)) h.update(NS(self.ourKexInitPayload)) @@ -992,7 +991,7 @@ f, packet = getMP(packet) signature, packet = getNS(packet) fingerprint = ':'.join(map(lambda c: '%02x'%ord(c), - md5.new(pubKey).digest())) + md5(pubKey).digest())) d = self.verifyHostKey(pubKey, fingerprint) d.addCallback(self._continueGEX_REPLY, pubKey, f, signature) d.addErrback( @@ -1015,7 +1014,7 @@ """ serverKey = keys.Key.fromString(pubKey) sharedSecret = _MPpow(f, self.x, self.p) - h = sha.new() + h = sha1() h.update(NS(self.ourVersionString)) h.update(NS(self.otherVersionString)) h.update(NS(self.ourKexInitPayload)) @@ -1169,9 +1168,9 @@ 'none':(None, 0, 0), } macMap = { - 'hmac-sha1': sha, + 'hmac-sha1': sha1, 'hmac-md5': md5, - 'none':None + 'none': None } @@ -1243,10 +1242,7 @@ mod = self.macMap[mac] if not mod: return (None, '', '', 0) - #if not hasattr(mod, 'digest_size'): - # ds = len(mod.new().digest()) - #else: - ds = mod.digest_size + ds = mod().digest_size key = key[:ds] + '\x00' * (64 - ds) i = XOR.new('\x36').encrypt(key) o = XOR.new('\x5c').encrypt(key) @@ -1287,8 +1283,8 @@ return '' data = struct.pack('>L', seqid) + data mod, i, o, ds = self.outMAC - inner = mod.new(i + data) - outer = mod.new(o + inner.digest()) + inner = mod(i + data) + outer = mod(o + inner.digest()) return outer.digest() @@ -1309,8 +1305,8 @@ return mac == '' data = struct.pack('>L', seqid) + data mod, i, o, ds = self.inMAC - inner = mod.new(i + data) - outer = mod.new(o + inner.digest()) + inner = mod(i + data) + outer = mod(o + inner.digest()) return mac == outer.digest() --- twisted/conch/test/test_ckeygen.py +++ twisted/conch/test/test_ckeygen.py @@ -0,0 +1,73 @@ +# Copyright (c) 2008 Twisted Matrix Laboratories. +# See LICENSE for details. + +""" +Tests for L{twisted.conch.scripts.ckeygen}. +""" + +import sys +from StringIO import StringIO + +from twisted.python.filepath import FilePath +from twisted.trial.unittest import TestCase +from twisted.conch.ssh.keys import Key +from twisted.conch.scripts.ckeygen import printFingerprint, _saveKey +from twisted.conch.test.keydata import publicRSA_openssh, privateRSA_openssh + + + +class KeyGenTests(TestCase): + """ + Tests for various functions used to implement the I{ckeygen} script. + """ + def setUp(self): + """ + Patch C{sys.stdout} with a L{StringIO} instance to tests can make + assertions about what's printed. + """ + self.stdout = StringIO() + self.patch(sys, 'stdout', self.stdout) + + + def test_printFingerprint(self): + """ + L{printFingerprint} writes a line to standard out giving the number of + bits of the key, its fingerprint, and the basename of the file from it + was read. + """ + filename = self.mktemp() + FilePath(filename).setContent(publicRSA_openssh) + printFingerprint({'filename': filename}) + self.assertEqual( + self.stdout.getvalue(), + '768 3d:13:5f:cb:c9:79:8a:93:06:27:65:bc:3d:0b:8f:af temp\n') + + + def test_saveKey(self): + """ + L{_saveKey} writes the private and public parts of a key to two + different files and writes a report of this to standard out. + """ + base = FilePath(self.mktemp()) + base.makedirs() + filename = base.child('id_rsa').path + key = Key.fromString(privateRSA_openssh) + _saveKey( + key.keyObject, + {'filename': filename, 'pass': 'passphrase'}) + self.assertEqual( + self.stdout.getvalue(), + "Your identification has been saved in %s\n" + "Your public key has been saved in %s.pub\n" + "The key fingerprint is:\n" + "3d:13:5f:cb:c9:79:8a:93:06:27:65:bc:3d:0b:8f:af\n" % ( + filename, + filename)) + self.assertEqual( + key.fromString( + base.child('id_rsa').getContent(), None, 'passphrase'), + key) + self.assertEqual( + Key.fromString(base.child('id_rsa.pub').getContent()), + key.public()) + --- twisted/conch/test/test_keys.py +++ twisted/conch/test/test_keys.py @@ -12,10 +12,11 @@ else: from twisted.conch.ssh import keys, common, sexpy, asn1 +import os, base64 from twisted.conch.test import keydata from twisted.python import randbytes +from twisted.python.hashlib import sha1 from twisted.trial import unittest -import sha, os, base64 class SSHKeysHandlingTestCase(unittest.TestCase): """ @@ -330,7 +331,7 @@ messageSize = 6 self.assertEquals(keys.pkcs1Pad(data, messageSize), '\x01\xff\x00ABC') - hash = sha.new().digest() + hash = sha1().digest() messageSize = 40 self.assertEquals(keys.pkcs1Digest('', messageSize), '\x01\xff\xff\xff\x00' + keys.ID_SHA1 + hash) @@ -362,7 +363,7 @@ """ data = 'data' key, sig = self._signDSA(data) - sigData = sha.new(data).digest() + sigData = sha1(data).digest() v = key.sign(sigData, '\x55' * 19) self.assertEquals(sig, common.NS('ssh-dss') + common.NS( Crypto.Util.number.long_to_bytes(v[0], 20) + --- twisted/conch/test/test_transport.py +++ twisted/conch/test/test_transport.py @@ -5,8 +5,6 @@ Tests for ssh/transport.py and the classes therein. """ -import md5, sha - try: import Crypto.Cipher.DES3 except ImportError: @@ -27,6 +25,7 @@ from twisted.protocols import loopback from twisted.python import randbytes from twisted.python.reflect import qual +from twisted.python.hashlib import md5, sha1 from twisted.conch.ssh import service from twisted.test import proto_helpers @@ -856,9 +855,8 @@ """ self.proto.sessionID = 'EF' - k1 = sha.new('AB' + 'CD' - + 'K' + self.proto.sessionID).digest() - k2 = sha.new('ABCD' + k1).digest() + k1 = sha1('AB' + 'CD' + 'K' + self.proto.sessionID).digest() + k2 = sha1('ABCD' + k1).digest() self.assertEquals(self.proto._getKey('K', 'AB', 'CD'), k1 + k2) @@ -1109,7 +1107,7 @@ f = common._MPpow(transport.DH_GENERATOR, y, transport.DH_PRIME) sharedSecret = common._MPpow(e, y, transport.DH_PRIME) - h = sha.new() + h = sha1() h.update(common.NS(self.proto.ourVersionString) * 2) h.update(common.NS(self.proto.ourKexInitPayload) * 2) h.update(common.NS(self.proto.factory.publicKeys['ssh-rsa'].blob())) @@ -1190,7 +1188,7 @@ y = common.getMP('\x00\x00\x00\x80' + '\x99' * 128)[0] f = common._MPpow(self.proto.g, y, self.proto.p) sharedSecret = common._MPpow(e, y, self.proto.p) - h = sha.new() + h = sha1() h.update(common.NS(self.proto.ourVersionString) * 2) h.update(common.NS(self.proto.ourKexInitPayload) * 2) h.update(common.NS(self.proto.factory.publicKeys['ssh-rsa'].blob())) @@ -1221,7 +1219,7 @@ y = common.getMP('\x00\x00\x00\x80' + '\x99' * 128)[0] f = common._MPpow(self.proto.g, y, self.proto.p) sharedSecret = common._MPpow(e, y, self.proto.p) - h = sha.new() + h = sha1() h.update(common.NS(self.proto.ourVersionString) * 2) h.update(common.NS(self.proto.ourKexInitPayload) * 2) h.update(common.NS(self.proto.factory.publicKeys['ssh-rsa'].blob())) @@ -1360,7 +1358,7 @@ self.calledVerifyHostKey = True self.assertEquals(pubKey, self.blob) self.assertEquals(fingerprint.replace(':', ''), - md5.new(pubKey).hexdigest()) + md5(pubKey).hexdigest()) return defer.succeed(True) @@ -1427,7 +1425,7 @@ sharedSecret = common._MPpow(transport.DH_GENERATOR, self.proto.x, transport.DH_PRIME) - h = sha.new() + h = sha1() h.update(common.NS(self.proto.ourVersionString) * 2) h.update(common.NS(self.proto.ourKexInitPayload) * 2) h.update(common.NS(self.blob)) @@ -1476,7 +1474,7 @@ self.test_KEX_DH_GEX_GROUP() sharedSecret = common._MPpow(3, self.proto.x, self.proto.p) - h = sha.new() + h = sha1() h.update(common.NS(self.proto.ourVersionString) * 2) h.update(common.NS(self.proto.ourKexInitPayload) * 2) h.update(common.NS(self.blob)) @@ -1654,7 +1652,7 @@ Crypto.Cipher.XOR.new('\x36').encrypt(key)) self.assertEquals(mod[2], Crypto.Cipher.XOR.new('\x5c').encrypt(key)) - self.assertEquals(mod[3], len(mod[0].new().digest())) + self.assertEquals(mod[3], len(mod[0]().digest())) def test_setKeysCiphers(self): @@ -1693,7 +1691,7 @@ outMac.setKeys('', '', '', '', key, '') inMac.setKeys('', '', '', '', '', key) if mod: - ds = mod.digest_size + ds = mod().digest_size else: ds = 0 self.assertEquals(inMac.verifyDigestSize, ds) @@ -1703,7 +1701,7 @@ data = key packet = '\x00' * 4 + key if mod: - mac = mod.new(o + mod.new(i + packet).digest()).digest() + mac = mod(o + mod(i + packet).digest()).digest() else: mac = '' self.assertEquals(outMac.makeMAC(seqid, data), mac) --- twisted/cred/util.py +++ twisted/cred/util.py @@ -1,30 +1,32 @@ - -# Copyright (c) 2001-2004 Twisted Matrix Laboratories. +# -*- test-case-name: twisted.test.test_newcred -*- +# Copyright (c) 2001-2008 Twisted Matrix Laboratories. # See LICENSE for details. - """ -Utility functions for authorization. +Outdated, deprecated functionality related to challenge-based authentication. -These are currently for challenge-response shared secret authentication. - -Maintainer: Glyph Lefkowitz +Seek a solution to your problem elsewhere. This module is deprecated. """ # System Imports -import md5 -import random +import random, warnings +from twisted.python.hashlib import md5 from twisted.cred.error import Unauthorized + def respond(challenge, password): """Respond to a challenge. This is useful for challenge/response authentication. """ - m = md5.new() + warnings.warn( + "twisted.cred.util.respond is deprecated since Twisted 8.3.", + category=PendingDeprecationWarning, + stacklevel=2) + m = md5() m.update(password) hashedPassword = m.digest() - m = md5.new() + m = md5() m.update(hashedPassword) m.update(challenge) doubleHashedPassword = m.digest() @@ -33,8 +35,12 @@ def challenge(): """I return some random data. """ + warnings.warn( + "twisted.cred.util.challenge is deprecated since Twisted 8.3.", + category=PendingDeprecationWarning, + stacklevel=2) crap = '' for x in range(random.randrange(15,25)): crap = crap + chr(random.randint(65,90)) - crap = md5.new(crap).digest() + crap = md5(crap).digest() return crap --- twisted/internet/_sslverify.py +++ twisted/internet/_sslverify.py @@ -1,11 +1,13 @@ # -*- test-case-name: twisted.test.test_sslverify -*- -# Copyright 2005 Divmod, Inc. See LICENSE file for details +# Copyright 2005 Divmod, Inc. # Copyright (c) 2005-2008 Twisted Matrix Laboratories. +# See LICENSE for details. -import itertools, md5 +import itertools from OpenSSL import SSL, crypto from twisted.python import reflect, util +from twisted.python.hashlib import md5 from twisted.internet.defer import Deferred from twisted.internet.error import VerifyError, CertificateError @@ -452,7 +454,7 @@ MD5 hex digest of signature on an empty certificate request with this key. """ - return md5.md5(self._emptyReq).hexdigest() + return md5(self._emptyReq).hexdigest() def inspect(self): @@ -736,7 +738,7 @@ ctx.set_options(self._OP_ALL) if self.enableSessions: - sessionName = md5.md5("%s-%d" % (reflect.qual(self.__class__), _sessionCounter())).hexdigest() + sessionName = md5("%s-%d" % (reflect.qual(self.__class__), _sessionCounter())).hexdigest() ctx.set_session_id(sessionName) if not self.enableSessionTickets: --- twisted/mail/maildir.py +++ twisted/mail/maildir.py @@ -12,7 +12,6 @@ import stat import socket import time -import md5 import cStringIO from zope.interface import implements @@ -27,6 +26,7 @@ from twisted.protocols import basic from twisted.persisted import dirdbm from twisted.python import log, failure +from twisted.python.hashlib import md5 from twisted.mail import mail from twisted.mail import alias from twisted.internet import interfaces, defer, reactor @@ -298,7 +298,7 @@ """ # Returning the actual filename is a mistake. Hash it. base = os.path.basename(self.list[i]) - return md5.md5(base).hexdigest() + return md5(base).hexdigest() def deleteMessage(self, i): """Delete a message @@ -355,7 +355,7 @@ return StringIO.StringIO(self.msgs[i]) def getUidl(self, i): - return md5.new(self.msgs[i]).hexdigest() + return md5(self.msgs[i]).hexdigest() def deleteMessage(self, i): pass --- twisted/mail/pop3.py +++ twisted/mail/pop3.py @@ -1,6 +1,6 @@ # -*- test-case-name: twisted.mail.test.test_pop3 -*- # -# Copyright (c) 2001-2004 Twisted Matrix Laboratories. +# Copyright (c) 2001-2008 Twisted Matrix Laboratories. # See LICENSE for details. @@ -14,7 +14,6 @@ import string import base64 import binascii -import md5 import warnings from zope.interface import implements, Interface @@ -26,6 +25,7 @@ from twisted.internet import defer from twisted.internet import interfaces from twisted.python import log +from twisted.python.hashlib import md5 from twisted import cred import twisted.cred.error @@ -44,7 +44,7 @@ def checkPassword(self, password): seed = self.magic + password - myDigest = md5.new(seed).hexdigest() + myDigest = md5(seed).hexdigest() return myDigest == self.digest @@ -1031,7 +1031,7 @@ self._dispatch(self.command+"_continue", None, line) def apopAuthenticate(self, user, password, magic): - digest = md5.new(magic + password).hexdigest() + digest = md5(magic + password).hexdigest() self.apop(user, digest) def apop(self, user, digest): --- twisted/mail/pop3client.py +++ twisted/mail/pop3client.py @@ -1,5 +1,6 @@ # -*- test-case-name: twisted.mail.test.test_pop3client -*- # Copyright (c) 2001-2004 Divmod Inc. +# Copyright (c) 2008 Twisted Matrix Laboratories. # See LICENSE for details. """ @@ -10,9 +11,10 @@ @author: Jp Calderone """ -import re, md5 +import re from twisted.python import log +from twisted.python.hashlib import md5 from twisted.internet import defer from twisted.protocols import basic from twisted.protocols import policies @@ -485,7 +487,7 @@ def _apop(self, username, password, challenge): # Internal helper. Computes and sends an APOP response. Returns # a Deferred that fires when the server responds to the response. - digest = md5.new(challenge + password).hexdigest() + digest = md5(challenge + password).hexdigest() return self.apop(username, digest) def apop(self, username, digest): --- twisted/mail/test/test_mail.py +++ twisted/mail/test/test_mail.py @@ -7,7 +7,6 @@ import os import errno -import md5 import shutil import pickle import StringIO @@ -32,6 +31,7 @@ from twisted.internet import address from twisted.python import failure from twisted.python.filepath import FilePath +from twisted.python.hashlib import md5 from twisted import mail import twisted.mail.mail @@ -587,7 +587,7 @@ shutil.rmtree(self.tmpdir) def testAuthenticateAPOP(self): - resp = md5.new(self.P.magic + 'password').hexdigest() + resp = md5(self.P.magic + 'password').hexdigest() return self.P.authenticateUserAPOP('user', resp ).addCallback(self._cbAuthenticateAPOP ) @@ -599,13 +599,13 @@ result[2]() def testAuthenticateIncorrectUserAPOP(self): - resp = md5.new(self.P.magic + 'password').hexdigest() + resp = md5(self.P.magic + 'password').hexdigest() return self.assertFailure( self.P.authenticateUserAPOP('resu', resp), cred.error.UnauthorizedLogin) def testAuthenticateIncorrectResponseAPOP(self): - resp = md5.new('wrong digest').hexdigest() + resp = md5('wrong digest').hexdigest() return self.assertFailure( self.P.authenticateUserAPOP('user', resp), cred.error.UnauthorizedLogin) --- twisted/news/database.py +++ twisted/news/database.py @@ -1,5 +1,5 @@ # -*- test-case-name: twisted.news.test.test_news -*- -# Copyright (c) 2001-2004 Twisted Matrix Laboratories. +# Copyright (c) 2001-2008 Twisted Matrix Laboratories. # See LICENSE for details. @@ -13,18 +13,19 @@ """ -from __future__ import nested_scopes +import getpass, pickle, time, socket +import os +import StringIO + +from zope.interface import implements, Interface from twisted.news.nntp import NNTPError from twisted.mail import smtp from twisted.internet import defer from twisted.enterprise import adbapi from twisted.persisted import dirdbm +from twisted.python.hashlib import md5 -import getpass, pickle, time, socket, md5 -import os -import StringIO -from zope.interface import implements, Interface ERR_NOGROUP, ERR_NOARTICLE = range(2, 4) # XXX - put NNTP values here (I guess?) @@ -53,15 +54,15 @@ if not self.getHeader('Message-ID'): s = str(time.time()) + self.body - id = hexdigest(md5.md5(s)) + '@' + socket.gethostname() + id = hexdigest(md5(s)) + '@' + socket.gethostname() self.putHeader('Message-ID', '<%s>' % id) if not self.getHeader('Bytes'): self.putHeader('Bytes', str(len(self.body))) - + if not self.getHeader('Lines'): self.putHeader('Lines', str(self.body.count('\n'))) - + if not self.getHeader('Date'): self.putHeader('Date', time.ctime(time.time())) @@ -83,7 +84,7 @@ for i in self.headers.values(): headers.append('%s: %s' % i) return '\r\n'.join(headers) + '\r\n' - + def overview(self): xover = [] for i in OVERVIEW_FMT: @@ -94,12 +95,12 @@ class NewsServerError(Exception): pass - + class INewsStorage(Interface): """ An interface for storing and requesting news articles """ - + def listRequest(): """ Returns a deferred whose callback will be passed a list of 4-tuples @@ -112,16 +113,16 @@ Returns a deferred whose callback will be passed the list of recommended subscription groups for new server users """ - - + + def postRequest(message): """ Returns a deferred whose callback will be invoked if 'message' is successfully posted to one or more specified groups and whose errback will be invoked otherwise. """ - - + + def overviewRequest(): """ Returns a deferred whose callback will be passed the a list of @@ -146,21 +147,21 @@ ends at the last article. """ - + def listGroupRequest(group): """ Returns a deferred whose callback will be passed a two-tuple of (group name, [article indices]) """ - - + + def groupRequest(group): """ Returns a deferred whose callback will be passed a five-tuple of (group name, article count, highest index, lowest index, group flags) """ - + def articleExistsRequest(id): """ Returns a deferred whose callback will be passed with a true value @@ -170,7 +171,7 @@ def articleRequest(group, index, id = None): - """ + """ Returns a deferred whose callback will be passed a file-like object containing the full article text (headers and body) for the article of the specified index in the specified group, and whose errback @@ -180,7 +181,7 @@ group. """ - + def headRequest(group, index): """ Returns a deferred whose callback will be passed the header for @@ -189,7 +190,7 @@ exist. """ - + def bodyRequest(group, index): """ Returns a deferred whose callback will be passed the body for @@ -231,7 +232,7 @@ class PickleStorage: """A trivial NewsStorage implementation using pickles - + Contains numerous flaws and is generally unsuitable for any real applications. Consider yourself warned! """ @@ -388,8 +389,8 @@ return defer.fail(ERR_NOARTICLE) else: return defer.fail(ERR_NOGROUP) - - + + def headRequest(self, group, index): if self.db.has_key(group): if self.db[group].has_key(index): @@ -441,7 +442,7 @@ minArticle = 1 maxArticle = 0 articles = None - + def __init__(self, name, flags = 'y'): self.name = name self.flags = flags @@ -452,9 +453,9 @@ """ A NewStorage implementation using Twisted's dirdbm persistence module. """ - - implements(INewsStorage) - + + implements(INewsStorage) + def __init__(self, mailhost, path): self.path = path self.mailhost = mailhost @@ -502,8 +503,8 @@ def subscriptionRequest(self): return defer.succeed(self.dbm['subscriptions']) - - + + def getModerator(self, groups): # first see if any groups are moderated. if so, nothing gets posted, # but the whole messages gets forwarded to the moderator address @@ -532,17 +533,17 @@ def postRequest(self, message): cleave = message.find('\r\n\r\n') headers, article = message[:cleave], message[cleave + 4:] - + article = Article(headers, article) groups = article.getHeader('Newsgroups').split() xref = [] - + # Check for moderated status moderator = self.getModerator(groups) if moderator and not article.getHeader('Approved'): return self.notifyModerator(moderator, article) - - + + for group in groups: try: g = self.dbm['groups'][group] @@ -570,7 +571,7 @@ def xoverRequest(self, group, low, high): if not self.dbm['groups'].has_key(group): return defer.succeed([]) - + if low is None: low = 0 if high is None: @@ -585,7 +586,7 @@ def xhdrRequest(self, group, low, high, header): if group not in self.dbm['groups']: return defer.succeed([]) - + if low is None: low = 0 if high is None: @@ -618,8 +619,8 @@ def articleExistsRequest(self, id): return defer.succeed(id in self.dbm['Message-IDs']) - - + + def articleRequest(self, group, index, id = None): if id is not None: try: @@ -629,7 +630,7 @@ else: group, index = xref[0] index = int(index) - + try: a = self.dbm['groups'][group].articles[index] except KeyError: @@ -640,8 +641,8 @@ a.getHeader('Message-ID'), StringIO.StringIO(a.textHeaders() + '\r\n' + a.body) )) - - + + def headRequest(self, group, index, id = None): if id is not None: try: @@ -651,7 +652,7 @@ else: group, index = xref[0] index = int(index) - + try: a = self.dbm['groups'][group].articles[index] except KeyError: @@ -669,7 +670,7 @@ else: group, index = xref[0] index = int(index) - + try: a = self.dbm['groups'][group].articles[index] except KeyError: @@ -690,7 +691,7 @@ CREATE TABLE groups ( group_id SERIAL, name VARCHAR(80) NOT NULL, - + flags INTEGER DEFAULT 0 NOT NULL ); @@ -700,7 +701,7 @@ CREATE TABLE articles ( article_id SERIAL, message_id TEXT, - + header TEXT, body TEXT ); @@ -719,16 +720,16 @@ CREATE TABLE subscriptions ( group_id INTEGER ); - + CREATE TABLE overview ( header TEXT ); """ - + def __init__(self, info): self.info = info self.dbpool = adbapi.ConnectionPool(**self.info) - + def __setstate__(self, state): self.__dict__ = state @@ -778,14 +779,14 @@ SELECT name, group_id FROM groups WHERE name IN (%s) """ % (', '.join([("'%s'" % (adbapi.safe(group),)) for group in groups]),) - + transaction.execute(sql) result = transaction.fetchall() - + # No relevant groups, bye bye! if not len(result): raise NNTPError('None of groups in Newsgroup header carried') - + # Got some groups, now find the indices this article will have in each sql = """ SELECT groups.group_id, COALESCE(MAX(postings.article_index), 0) + 1 @@ -800,20 +801,20 @@ if not len(indices): raise NNTPError('Internal server error - no indices found') - + # Associate indices with group names gidToName = dict([(b, a) for (a, b) in result]) gidToIndex = dict(indices) - + nameIndex = [] for i in gidToName: nameIndex.append((gidToName[i], gidToIndex[i])) - + # Build xrefs xrefs = socket.gethostname().split()[0] xrefs = xrefs + ' ' + ' '.join([('%s:%d' % (group, id)) for (group, id) in nameIndex]) article.putHeader('Xref', xrefs) - + # Hey! The article is ready to be posted! God damn f'in finally. sql = """ INSERT INTO articles (message_id, header, body) @@ -823,9 +824,9 @@ adbapi.safe(article.textHeaders()), adbapi.safe(article.body) ) - + transaction.execute(sql) - + # Now update the posting to reflect the groups to which this belongs for gid in gidToName: sql = """ @@ -833,7 +834,7 @@ VALUES (%d, (SELECT last_value FROM articles_article_id_seq), %d) """ % (gid, gidToIndex[gid]) transaction.execute(sql) - + return len(nameIndex) @@ -888,13 +889,13 @@ WHERE postings.group_id = groups.group_id AND groups.name = '%s' """ % (adbapi.safe(group),) - + return self.dbpool.runQuery(sql).addCallback( lambda results, group = group: (group, [res[0] for res in results]) ) - def groupRequest(self, group): + def groupRequest(self, group): sql = """ SELECT groups.name, COUNT(postings.article_index), @@ -906,7 +907,7 @@ WHERE groups.name = '%s' GROUP BY groups.name, groups.flags """ % (adbapi.safe(group),) - + return self.dbpool.runQuery(sql).addCallback( lambda results: tuple(results[0]) ) @@ -917,7 +918,7 @@ SELECT COUNT(message_id) FROM articles WHERE message_id = '%s' """ % (adbapi.safe(id),) - + return self.dbpool.runQuery(sql).addCallback( lambda result: bool(result[0][0]) ) @@ -933,7 +934,7 @@ AND groups.group_id = postings.group_id """ % (adbapi.safe(id), adbapi.safe(group)) else: - sql = """ + sql = """ SELECT postings.article_index, articles.message_id, articles.header, articles.body FROM groups,articles LEFT OUTER JOIN postings ON postings.article_id = articles.article_id @@ -960,7 +961,7 @@ AND postings.group_id = groups.group_id AND groups.name = '%s' """ % (index, adbapi.safe(group)) - + return self.dbpool.runQuery(sql).addCallback(lambda result: result[0]) @@ -973,7 +974,7 @@ AND postings.group_id = groups.group_id AND groups.name = '%s' """ % (index, adbapi.safe(group)) - + return self.dbpool.runQuery(sql).addCallback( lambda result: result[0] ).addCallback( --- twisted/persisted/sob.py +++ twisted/persisted/sob.py @@ -1,5 +1,5 @@ # -*- test-case-name: twisted.test.test_sob -*- -# Copyright (c) 2001-2004 Twisted Matrix Laboratories. +# Copyright (c) 2001-2008 Twisted Matrix Laboratories. # See LICENSE for details. # @@ -9,7 +9,7 @@ Maintainer: Moshe Zadka """ -import os, md5, sys +import os, sys try: import cPickle as pickle except ImportError: @@ -19,6 +19,7 @@ except ImportError: import StringIO from twisted.python import log, runtime +from twisted.python.hashlib import md5 from twisted.persisted import styles from zope.interface import implements, Interface @@ -31,11 +32,11 @@ leftover = len(data) % cipher.block_size if leftover: data += ' '*(cipher.block_size - leftover) - return cipher.new(md5.new(passphrase).digest()[:16]).encrypt(data) + return cipher.new(md5(passphrase).digest()[:16]).encrypt(data) def _decrypt(passphrase, data): from Crypto.Cipher import AES - return AES.new(md5.new(passphrase).digest()[:16]).decrypt(data) + return AES.new(md5(passphrase).digest()[:16]).decrypt(data) class IPersistable(Interface): --- twisted/protocols/sip.py +++ twisted/protocols/sip.py @@ -1,6 +1,6 @@ # -*- test-case-name: twisted.test.test_sip -*- -# Copyright (c) 2001-2004 Twisted Matrix Laboratories. +# Copyright (c) 2001-2008 Twisted Matrix Laboratories. # See LICENSE for details. @@ -14,12 +14,12 @@ import socket import random import time -import md5 import sys from zope.interface import implements, Interface # twisted imports from twisted.python import log, util +from twisted.python.hashlib import md5 from twisted.internet import protocol, defer, reactor from twisted import cred @@ -132,7 +132,7 @@ pszNonce, pszCNonce, ): - m = md5.md5() + m = md5() m.update(pszUserName) m.update(":") m.update(pszRealm) @@ -140,7 +140,7 @@ m.update(pszPassword) HA1 = m.digest() if pszAlg == "md5-sess": - m = md5.md5() + m = md5() m.update(HA1) m.update(":") m.update(pszNonce) @@ -159,7 +159,7 @@ pszDigestUri, pszHEntity, ): - m = md5.md5() + m = md5() m.update(pszMethod) m.update(":") m.update(pszDigestUri) @@ -168,7 +168,7 @@ m.update(pszHEntity) HA2 = m.digest().encode('hex') - m = md5.md5() + m = md5() m.update(HA1) m.update(":") m.update(pszNonce) --- twisted/python/filepath.py +++ twisted/python/filepath.py @@ -9,7 +9,6 @@ import os import errno import random -import sha import base64 from os.path import isabs, exists, normpath, abspath, splitext @@ -25,6 +24,7 @@ # modified for inclusion in the standard library. --glyph from twisted.python.runtime import platform +from twisted.python.hashlib import sha1 from twisted.python.win32 import ERROR_FILE_NOT_FOUND, ERROR_PATH_NOT_FOUND from twisted.python.win32 import ERROR_INVALID_NAME, ERROR_DIRECTORY @@ -120,7 +120,7 @@ """ Create a pseudorandom, 16-character string for use in secure filenames. """ - return armor(sha.new(randomBytes(64)).digest())[:16] + return armor(sha1(randomBytes(64)).digest())[:16] --- twisted/python/hashlib.py +++ twisted/python/hashlib.py @@ -0,0 +1,24 @@ +# -*- test-case-name: twisted.python.test.test_hashlib -*- +# Copyright (c) 2008 Twisted Matrix Laboratories. +# See LICENSE for details. + +""" +L{twisted.python.hashlib} presents a subset of the interface provided by +U{hashlib<http://docs.python.org/library/hashlib.html>}. The subset is the +interface required by various parts of Twisted. This allows application code +to transparently use APIs which existed before C{hashlib} was introduced or to +use C{hashlib} if it is available. +""" + + +try: + _hashlib = __import__("hashlib") +except ImportError: + from md5 import md5 + from sha import sha as sha1 +else: + md5 = _hashlib.md5 + sha1 = _hashlib.sha1 + + +__all__ = ["md5", "sha1"] --- twisted/python/otp.py +++ twisted/python/otp.py @@ -1,7 +1,9 @@ -# Copyright (c) 2001-2004 Twisted Matrix Laboratories. +# -*- test-case-name: twisted.python.test.test_otp -*- +# Copyright (c) 2001-2008 Twisted Matrix Laboratories. # See LICENSE for details. -""" A One-Time Password System based on RFC 2289 +""" +A One-Time Password System based on RFC 2289 The class Authenticator contains the hashing-logic, and the parser for the readable output. It also contains challenge which returns a string describing @@ -17,11 +19,21 @@ Uses the MD5- and SHA-algorithms for hashing Todo: RFC2444, SASL (perhaps), parsing hex-responses + +This module is deprecated. Consider using U{another Python OTP +library<http://labix.org/python-otp>} instead. """ +import warnings import string import random +warnings.warn( + "twisted.python.otp is deprecated since Twisted 8.3.", + category=DeprecationWarning, + stacklevel=2) + + def stringToLong(s): """ Convert digest to long """ result = 0L @@ -47,33 +59,37 @@ result = chr(l % 256) + result l = l / 256L return result - -import md5, sha -hashid = {md5: 'md5', sha: 'sha1'} + +from twisted.python.hashlib import md5, sha1 +hashid = {md5: 'md5', sha1: 'sha1'} INITIALSEQUENCE = 1000 MINIMUMSEQUENCE = 50 class Unauthorized(Exception): """the Unauthorized exception - + This exception is raised when an action is not allowed, or a user is not authenticated properly. """ class OTPAuthenticator: - """A One Time Password System - + """ + A One Time Password System + Based on RFC 2289, which is based on a the S/KEY Authentication-scheme. It uses the MD5- and SHA-algorithms for hashing - - The variable OTP is at all times a 64bit string""" + The variable OTP is at all times a 64bit string. + + @ivar hash: An object which can be used to compute hashes. This is either + L{md5} or L{sha1}. + """ def __init__(self, hash = md5): "Set the hash to either md5 or sha1" self.hash = hash - pass - + + def generateSeed(self): "Return a 10 char random seed, with 6 lowercase chars and 4 digits" seed = '' @@ -86,9 +102,9 @@ def foldDigest(self, otp): if self.hash == md5: return self.foldDigest128(otp) - if self.hash == sha: + if self.hash == sha1: return self.foldDigest160(otp) - + def foldDigest128(self, otp128): "Fold a 128 bit digest to 64 bit" regs = stringToDWords(otp128) @@ -120,9 +136,9 @@ def hashUpdate(self, digest): "Run through the hash and fold to 64 bit" - h = self.hash.new(digest) + h = self.hash(digest) return self.foldDigest(h.digest()) - + def generateOTP(self, seed, passwd, sequence): """Return a 64 bit OTP based on inputs Run through makeReadable to get a 6 word pass-phrase""" @@ -138,7 +154,7 @@ for i in xrange(0, 64, 2): parity = parity + otp & 0x3 otp = otp >> 2 - return parity + return parity def makeReadable(self, otp): "Returns a 6 word pass-phrase from a 64bit OTP" @@ -151,7 +167,7 @@ return string.join(list) def challenge(self, seed, sequence): - """Return a challenge in the format otp-<hash> <sequence> <seed>""" + """Return a challenge in the format otp-<hash> <sequence> <seed>""" return "otp-%s %i %s" % (hashid[self.hash], sequence, seed) def parsePhrase(self, phrase): @@ -178,9 +194,9 @@ On the next authentication, the stored password is hashed and checked up against the one given by the user. If they match, the sequencecounter is decreased and the circle is closed. - + This object should be glued to each user - + Note: It does NOT reset the sequence when the combinations left approach zero, This has to be done manuelly by instancing a new object @@ -478,4 +494,3 @@ "WORM", "WORN", "WOVE", "WRIT", "WYNN", "YALE", "YANG", "YANK", "YARD", "YARN", "YAWL", "YAWN", "YEAH", "YEAR", "YELL", "YOGA", "YOKE"] - --- twisted/python/test/test_hashlib.py +++ twisted/python/test/test_hashlib.py @@ -0,0 +1,90 @@ +# Copyright (c) 2008 Twisted Matrix Laboratories. +# See LICENSE for details. + +""" +Tests for L{twisted.python.hashlib} +""" + +from twisted.trial.unittest import TestCase + +from twisted.python.hashlib import md5, sha1 + + +class HashObjectTests(TestCase): + """ + Tests for the hash object APIs presented by L{hashlib}, C{md5} and C{sha1}. + """ + def test_md5(self): + """ + L{hashlib.md5} returns an object which can be used to compute an MD5 + hash as defined by U{RFC 1321<http://www.ietf.org/rfc/rfc1321.txt>}. + """ + # Test the result using values from section A.5 of the RFC. + self.assertEqual( + md5().hexdigest(), "d41d8cd98f00b204e9800998ecf8427e") + self.assertEqual( + md5("a").hexdigest(), "0cc175b9c0f1b6a831c399e269772661") + self.assertEqual( + md5("abc").hexdigest(), "900150983cd24fb0d6963f7d28e17f72") + self.assertEqual( + md5("message digest").hexdigest(), + "f96b697d7cb7938d525a2f31aaf161d0") + self.assertEqual( + md5("abcdefghijklmnopqrstuvwxyz").hexdigest(), + "c3fcd3d76192e4007dfb496cca67e13b") + self.assertEqual( + md5("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz" + "0123456789").hexdigest(), + "d174ab98d277d9f5a5611c2c9f419d9f") + self.assertEqual( + md5("1234567890123456789012345678901234567890123456789012345678901" + "2345678901234567890").hexdigest(), + "57edf4a22be3c955ac49da2e2107b67a") + + # It should have digest and update methods, too. + self.assertEqual( + md5().digest().encode('hex'), + "d41d8cd98f00b204e9800998ecf8427e") + hash = md5() + hash.update("a") + self.assertEqual( + hash.digest().encode('hex'), + "0cc175b9c0f1b6a831c399e269772661") + + # Instances of it should have a digest_size attribute + self.assertEqual(md5().digest_size, 16) + + + def test_sha1(self): + """ + L{hashlib.sha1} returns an object which can be used to compute a SHA1 + hash as defined by U{RFC 3174<http://tools.ietf.org/rfc/rfc3174.txt>}. + """ + def format(s): + return ''.join(s.split()).lower() + # Test the result using values from section 7.3 of the RFC. + self.assertEqual( + sha1("abc").hexdigest(), + format( + "A9 99 3E 36 47 06 81 6A BA 3E 25 71 78 50 C2 6C 9C D0 D8 9D")) + self.assertEqual( + sha1("abcdbcdecdefdefgefghfghighijhi" + "jkijkljklmklmnlmnomnopnopq").hexdigest(), + format( + "84 98 3E 44 1C 3B D2 6E BA AE 4A A1 F9 51 29 E5 E5 46 70 F1")) + + # It should have digest and update methods, too. + self.assertEqual( + sha1("abc").digest().encode('hex'), + format( + "A9 99 3E 36 47 06 81 6A BA 3E 25 71 78 50 C2 6C 9C D0 D8 9D")) + hash = sha1() + hash.update("abc") + self.assertEqual( + hash.digest().encode('hex'), + format( + "A9 99 3E 36 47 06 81 6A BA 3E 25 71 78 50 C2 6C 9C D0 D8 9D")) + + # Instances of it should have a digest_size attribute. + self.assertEqual( + sha1().digest_size, 20) --- twisted/python/test/test_zipstream.py +++ twisted/python/test/test_zipstream.py @@ -6,10 +6,10 @@ """ import sys import random -import md5 import zipfile from twisted.python import zipstream, filepath +from twisted.python.hashlib import md5 from twisted.trial import unittest class FileEntryMixin: @@ -347,7 +347,7 @@ unzipIterChunky should unzip the given number of bytes per iteration. """ junk = ' '.join([str(random.random()) for n in xrange(1000)]) - junkmd5 = md5.new(junk).hexdigest() + junkmd5 = md5(junk).hexdigest() tempdir = filepath.FilePath(self.mktemp()) tempdir.makedirs() @@ -364,7 +364,7 @@ for r in uziter: pass self.assertEqual(r, 0) - newmd5 = md5.new( + newmd5 = md5( tempdir.child("zipstreamjunk").open().read()).hexdigest() self.assertEqual(newmd5, junkmd5) --- twisted/spread/pb.py +++ twisted/spread/pb.py @@ -27,7 +27,6 @@ @author: Glyph Lefkowitz """ -import md5 import random import new import types @@ -38,6 +37,7 @@ from twisted.python import log, failure, reflect from twisted.python.versions import Version from twisted.python.deprecate import deprecated +from twisted.python.hashlib import md5 from twisted.internet import defer, protocol from twisted.cred.portal import Portal from twisted.cred.credentials import IAnonymous, ICredentials @@ -997,10 +997,10 @@ This is useful for challenge/response authentication. """ - m = md5.new() + m = md5() m.update(password) hashedPassword = m.digest() - m = md5.new() + m = md5() m.update(hashedPassword) m.update(challenge) doubleHashedPassword = m.digest() @@ -1011,7 +1011,7 @@ crap = '' for x in range(random.randrange(15,25)): crap = crap + chr(random.randint(65,90)) - crap = md5.new(crap).digest() + crap = md5(crap).digest() return crap @@ -1340,12 +1340,12 @@ # IUsernameHashedPassword: def checkPassword(self, password): - return self.checkMD5Password(md5.md5(password).digest()) + return self.checkMD5Password(md5(password).digest()) # IUsernameMD5Password def checkMD5Password(self, md5Password): - md = md5.new() + md = md5() md.update(md5Password) md.update(self.challenge) correct = md.digest() --- twisted/test/test_newcred.py +++ twisted/test/test_newcred.py @@ -1,8 +1,8 @@ -# Copyright (c) 2001-2007 Twisted Matrix Laboratories. +# Copyright (c) 2001-2008 Twisted Matrix Laboratories. # See LICENSE for details. """ -Now with 30% more starch. +Tests for L{twisted.cred}, now with 30% more starch. """ @@ -10,7 +10,7 @@ from zope.interface import implements, Interface from twisted.trial import unittest -from twisted.cred import portal, checkers, credentials, error +from twisted.cred import portal, checkers, credentials, error, util from twisted.python import components from twisted.internet import defer from twisted.internet.defer import deferredGenerator as dG, waitForDeferred as wFD @@ -27,6 +27,49 @@ else: from twisted.cred import pamauth + +class DeprecatedUtilTests(unittest.TestCase): + """ + Tests for the deprecation of the functions in L{twisted.cred.util}. + """ + def test_respond(self): + """ + L{respond} applies a particular hashing to a challenge and a password + and returns the result. It is deprecated and calling it emits a + deprecation warning. + """ + # Use some values and test against the known correct output. + self.assertEqual( + util.respond('foo', 'bar').encode('hex'), + 'ebe4a2902532198cafaa223fb5ac0f20') + + warnings = self.flushWarnings(offendingFunctions=[self.test_respond]) + self.assertEqual( + warnings[0]['message'], + 'twisted.cred.util.respond is deprecated since Twisted 8.3.') + self.assertEqual( + warnings[0]['category'], + PendingDeprecationWarning) + self.assertEqual(len(warnings), 1) + + + def test_challenge(self): + """ + L{challenge} returns a different string each time it is called. + """ + self.assertNotEqual(util.challenge(), util.challenge()) + warnings = self.flushWarnings(offendingFunctions=[self.test_challenge]) + for w in warnings: + self.assertEqual( + w['message'], + 'twisted.cred.util.challenge is deprecated since Twisted 8.3.') + self.assertEqual( + w['category'], + PendingDeprecationWarning) + self.assertEqual(len(warnings), 2) + + + class ITestable(Interface): pass --- twisted/trial/test/test_loader.py +++ twisted/trial/test/test_loader.py @@ -5,12 +5,12 @@ Tests for loading tests by name. """ -import md5 import os import shutil import sys from twisted.python import util +from twisted.python.hashlib import md5 from twisted.trial.test import packages from twisted.trial import runner, reporter, unittest from twisted.trial.itrial import ITestCase @@ -484,7 +484,7 @@ # if isinstance(s, type) or isinstance(s, types.ClassType): # return s.__module__+'.'+s.__name__ n = runner.name(s) - d = md5.new(n).hexdigest() + d = md5(n).hexdigest() return d self.loadSortedPackages(sillySorter) --- twisted/web/_auth/digest.py +++ twisted/web/_auth/digest.py @@ -9,10 +9,10 @@ """ import time -import md5, sha from zope.interface import implements +from twisted.python.hashlib import md5, sha1 from twisted.python.randbytes import secureRandom from twisted.cred import credentials, error from twisted.web.iweb import ICredentialFactory, IUsernameDigestHash @@ -21,7 +21,7 @@ # The digest math algorithms = { - 'md5': md5.new, + 'md5': md5, # md5-sess is more complicated than just another algorithm. It requires # H(A1) state to be remembered from the first WWW-Authenticate challenge @@ -30,9 +30,9 @@ # recalculate H(A1) each time an Authorization header is received. Read # RFC 2617, section 3.2.2.2 and do not try to make DigestCredentialFactory # support this unless you completely understand it. -exarkun - 'md5-sess': md5.new, + 'md5-sess': md5, - 'sha': sha.new, + 'sha': sha1, } # DigestCalcHA1 @@ -257,7 +257,7 @@ if clientip is None: clientip = '' key = "%s,%s,%s" % (nonce, clientip, now) - digest = md5.new(key + self.privateKey).hexdigest() + digest = md5(key + self.privateKey).hexdigest() ekey = key.encode('base64') return "%s-%s" % (digest, ekey.strip('\n')) @@ -315,7 +315,7 @@ 'Invalid response, incompatible opaque/nonce too old') # Verify the digest - digest = md5.new(key + self.privateKey).hexdigest() + digest = md5(key + self.privateKey).hexdigest() if digest != opaqueParts[0]: raise error.LoginFailed('Invalid response, invalid opaque value') --- twisted/web/monitor.py +++ twisted/web/monitor.py @@ -1,85 +0,0 @@ -# Copyright (c) 2001-2004 Twisted Matrix Laboratories. -# See LICENSE for details. - -# -from twisted.web import client -from twisted.internet import reactor -import md5 -from zope.interface import implements - -class IChangeNotified: - pass - -class BaseChangeNotified: - - implements(IChangeNotified) - - def reportChange(self, old, new): - pass - - def reportNoChange(self): - pass - -class ChangeChecker: - - working = 0 - call = None - - def __init__(self, notified, url, delay=60): - self.notified = notified - self.url = url - self.md5 = None - self.delay = delay - - def start(self): - self.working = 1 - self._getPage() - - def stop(self): - if self.call: - self.call.cancel() - self.call = None - self.working = 0 - - def _getPage(self): - d = client.getPage(self.url) - d.addErrback(self.noPage) - d.addCallback(self.page) - self.call = None - - def noPage(self, e): - self.gotMD5(None) - - def page(self, p): - if p is None: - return self.gotMD5(None) - m = md5.new() - m.update(p) - self.gotMD5(m.digest()) - - def gotMD5(self, md5): - if not self.working: - return - if md5 != self.md5: - self.notified.reportChange(self.md5, md5) - self.md5 = md5 - else: - self.notified.reportNoChange() - if not self.call: - self.call = reactor.callLater(self.delay, self._getPage) - - -class ProxyChangeChecker(ChangeChecker): - - def __init__(self, proxyHost, proxyPort, notified, url, delay=60): - self.proxyHost = proxyHost - self.proxyPort = proxyPort - ChangeChecker.__init__(self, notified, url, delay) - - def _getPage(self): - factory = client.HTTPClientFactory(self.proxyHost, self.url) - factory.headers = {'pragma': 'no-cache'} - reactor.connectTCP(self.proxyHost, self.proxyPort, factory) - d = factory.deferred - d.addErrback(self.noPage) - d.addCallback(self.page) --- twisted/web/server.py +++ twisted/web/server.py @@ -1,6 +1,6 @@ # -*- test-case-name: twisted.web.test.test_web -*- -# Copyright (c) 2001-2004 Twisted Matrix Laboratories. +# Copyright (c) 2001-2008 Twisted Matrix Laboratories. # See LICENSE for details. @@ -507,9 +507,10 @@ """ (internal) Generate an opaque, unique ID for a user's session. """ - import md5, random + from twisted.python.hashlib import md5 + import random self.counter = self.counter + 1 - return md5.new("%s_%s" % (str(random.random()) , str(self.counter))).hexdigest() + return md5("%s_%s" % (str(random.random()) , str(self.counter))).hexdigest() def makeSession(self): """ --- twisted/web/test/test_httpauth.py +++ twisted/web/test/test_httpauth.py @@ -5,11 +5,11 @@ Tests for L{twisted.web._auth}. """ -import md5, sha from zope.interface import implements from zope.interface.verify import verifyObject +from twisted.python.hashlib import md5, sha1 from twisted.trial import unittest from twisted.cred import error, portal from twisted.cred.checkers import InMemoryUsernamePasswordDatabaseDontUse @@ -181,7 +181,7 @@ self.algorithm, self.realm) - def test_MD5HashA1(self, _algorithm='md5', _hash=md5.md5): + def test_MD5HashA1(self, _algorithm='md5', _hash=md5): """ L{calcHA1} accepts the C{'md5'} algorithm and returns an MD5 hash of its parameters, excluding the nonce and cnonce. @@ -203,9 +203,9 @@ hashA1 = calcHA1('md5-sess', self.username, self.realm, self.password, nonce, self.cnonce) a1 = '%s:%s:%s' % (self.username, self.realm, self.password) - ha1 = md5.md5(a1).digest() + ha1 = md5(a1).digest() a1 = '%s:%s:%s' % (ha1, nonce, self.cnonce) - expected = md5.md5(a1).hexdigest() + expected = md5(a1).hexdigest() self.assertEqual(hashA1, expected) @@ -214,10 +214,10 @@ L{calcHA1} accepts the C{'sha'} algorithm and returns a SHA hash of its parameters, excluding the nonce and cnonce. """ - self.test_MD5HashA1('sha', sha.sha) + self.test_MD5HashA1('sha', sha1) - def test_MD5HashA2Auth(self, _algorithm='md5', _hash=md5.md5): + def test_MD5HashA2Auth(self, _algorithm='md5', _hash=md5): """ L{calcHA2} accepts the C{'md5'} algorithm and returns an MD5 hash of its arguments, excluding the entity hash for QOP other than @@ -230,7 +230,7 @@ self.assertEqual(hashA2, expected) - def test_MD5HashA2AuthInt(self, _algorithm='md5', _hash=md5.md5): + def test_MD5HashA2AuthInt(self, _algorithm='md5', _hash=md5): """ L{calcHA2} accepts the C{'md5'} algorithm and returns an MD5 hash of its arguments, including the entity hash for QOP of C{'auth-int'}. @@ -265,7 +265,7 @@ its arguments, excluding the entity hash for QOP other than C{'auth-int'}. """ - self.test_MD5HashA2Auth('sha', sha.sha) + self.test_MD5HashA2Auth('sha', sha1) def test_SHAHashA2AuthInt(self): @@ -273,10 +273,10 @@ L{calcHA2} accepts the C{'sha'} algorithm and returns a SHA hash of its arguments, including the entity hash for QOP of C{'auth-int'}. """ - self.test_MD5HashA2AuthInt('sha', sha.sha) + self.test_MD5HashA2AuthInt('sha', sha1) - def test_MD5HashResponse(self, _algorithm='md5', _hash=md5.md5): + def test_MD5HashResponse(self, _algorithm='md5', _hash=md5): """ L{calcResponse} accepts the C{'md5'} algorithm and returns an MD5 hash of its parameters, excluding the nonce count, client nonce, and QoP @@ -308,10 +308,10 @@ of its parameters, excluding the nonce count, client nonce, and QoP value if the nonce count and client nonce are C{None} """ - self.test_MD5HashResponse('sha', sha.sha) + self.test_MD5HashResponse('sha', sha1) - def test_MD5HashResponseExtra(self, _algorithm='md5', _hash=md5.md5): + def test_MD5HashResponseExtra(self, _algorithm='md5', _hash=md5): """ L{calcResponse} accepts the C{'md5'} algorithm and returns an MD5 hash of its parameters, including the nonce count, client nonce, and QoP @@ -348,7 +348,7 @@ of its parameters, including the nonce count, client nonce, and QoP value if they are specified. """ - self.test_MD5HashResponseExtra('sha', sha.sha) + self.test_MD5HashResponseExtra('sha', sha1) def makeRequest(self, method='GET', clientAddress=None): @@ -639,7 +639,7 @@ self.assertTrue(verifyObject(IUsernameDigestHash, creds)) cleartext = '%s:%s:%s' % (self.username, self.realm, self.password) - hash = md5.md5(cleartext) + hash = md5(cleartext) self.assertTrue(creds.checkHash(hash.hexdigest())) hash.update('wrong') self.assertFalse(creds.checkHash(hash.hexdigest())) @@ -761,7 +761,7 @@ key = '%s,%s,%s' % (challenge['nonce'], self.clientAddress.host, '-137876876') - digest = md5.md5(key + credentialFactory.privateKey).hexdigest() + digest = md5(key + credentialFactory.privateKey).hexdigest() ekey = b64encode(key) oldNonceOpaque = '%s-%s' % (digest, ekey.strip('\n')) @@ -786,7 +786,7 @@ self.clientAddress.host, '0') - digest = md5.md5(key + 'this is not the right pkey').hexdigest() + digest = md5(key + 'this is not the right pkey').hexdigest() badChecksum = '%s-%s' % (digest, b64encode(key)) self.assertRaises( --- twisted/web/woven/guard.py +++ twisted/web/woven/guard.py @@ -1,6 +1,6 @@ # -*- test-case-name: twisted.web.test.test_woven -*- -# Copyright (c) 2001-2004 Twisted Matrix Laboratories. +# Copyright (c) 2001-2008 Twisted Matrix Laboratories. # See LICENSE for details. # @@ -16,12 +16,12 @@ import random import time -import md5 import urllib # Twisted Imports from twisted.python import log, components +from twisted.python.hashlib import md5 from twisted.web.resource import Resource, IResource from twisted.web.util import redirectTo, Redirect, DeferredResource from twisted.web.static import addSlash @@ -29,7 +29,7 @@ from twisted.cred.error import LoginFailed, UnauthorizedLogin def _sessionCookie(): - return md5.new("%s_%s" % (str(random.random()) , str(time.time()))).hexdigest() + return md5("%s_%s" % (str(random.random()) , str(time.time()))).hexdigest() class GuardSession(components.Componentized): """A user's session with a system. --- twisted/words/protocols/jabber/sasl_mechanisms.py +++ twisted/words/protocols/jabber/sasl_mechanisms.py @@ -1,16 +1,18 @@ # -*- test-case-name: twisted.words.test.test_jabbersaslmechanisms -*- # -# Copyright (c) 2001-2007 Twisted Matrix Laboratories. +# Copyright (c) 2001-2008 Twisted Matrix Laboratories. # See LICENSE for details. """ Protocol agnostic implementations of SASL authentication mechanisms. """ -import md5, binascii, random, time, os +import binascii, random, time, os from zope.interface import Interface, Attribute, implements +from twisted.python.hashlib import md5 + class ISASLMechanism(Interface): name = Attribute("""Common name for the SASL Mechanism.""") @@ -178,7 +180,7 @@ """ def H(s): - return md5.new(s).digest() + return md5(s).digest() def HEX(n): return binascii.b2a_hex(n) @@ -221,4 +223,4 @@ def _gen_nonce(self): - return md5.new("%s:%s:%s" % (str(random.random()) , str(time.gmtime()),str(os.getpid()))).hexdigest() + return md5("%s:%s:%s" % (str(random.random()) , str(time.gmtime()),str(os.getpid()))).hexdigest() --- twisted/words/protocols/jabber/xmlstream.py +++ twisted/words/protocols/jabber/xmlstream.py @@ -42,8 +42,8 @@ """ Create a SHA1-digest string of a session identifier and password. """ - import sha - return sha.new("%s%s" % (sid, password)).hexdigest() + from twisted.python.hashlib import sha1 + return sha1("%s%s" % (sid, password)).hexdigest() --- twisted/words/protocols/msn.py +++ twisted/words/protocols/msn.py @@ -1,9 +1,7 @@ # -*- test-case-name: twisted.words.test -*- -# Copyright (c) 2001-2005 Twisted Matrix Laboratories. +# Copyright (c) 2001-2008 Twisted Matrix Laboratories. # See LICENSE for details. -# - """ MSNP8 Protocol (client only) - semi-experimental @@ -18,7 +16,7 @@ You will want to subclass this and handle the gotNotificationReferral method appropriately. - + I{Notification Server} The NotificationClient class handles connections to the @@ -73,11 +71,12 @@ @author: Sam Jordan """ -import types, operator, os, md5 +import types, operator, os from random import randint from urllib import quote, unquote from twisted.python import failure, log +from twisted.python.hashlib import md5 from twisted.internet import reactor from twisted.internet.defer import Deferred from twisted.internet.protocol import ClientFactory @@ -185,7 +184,7 @@ class PassportNexus(HTTPClient): - + """ Used to obtain the URL of a valid passport login HTTPS server. @@ -330,7 +329,7 @@ If set to MESSAGE_ACK_NONE the server will do nothing. This is relevant for the return value of SwitchboardClient.sendMessage (which will return - a Deferred if ack is set to either MESSAGE_ACK or MESSAGE_NACK + a Deferred if ack is set to either MESSAGE_ACK or MESSAGE_NACK and will fire when the respective ACK or NACK is received). If set to MESSAGE_ACK_NONE sendMessage will return None. """ @@ -379,7 +378,7 @@ self.message = message class MSNContact: - + """ This class represents a contact (user). @@ -401,7 +400,7 @@ @ivar hasPager: Whether or not this user has a mobile pager (true=yes, false=no) """ - + def __init__(self, userHandle="", screenName="", lists=0, groups=[], status=None): self.userHandle = userHandle self.screenName = screenName @@ -856,7 +855,7 @@ def handle_CHL(self, params): checkParamLen(len(params), 2, 'CHL') self.sendLine("QRY %s msmsgs@msnmsgr.com 32" % self._nextTransactionID()) - self.transport.write(md5.md5(params[1] + MSN_CHALLENGE_STR).hexdigest()) + self.transport.write(md5(params[1] + MSN_CHALLENGE_STR).hexdigest()) def handle_QRY(self, params): pass @@ -1253,7 +1252,7 @@ a tuple with the new status code as the only element. """ - + id, d = self._createIDMapping() self.sendLine("CHG %s %s" % (id, status)) def _cb(r): @@ -1304,7 +1303,7 @@ the state as 'bl' which the official client interprets as -> allow messages from all users except those on the block list. - + @return: A Deferred, the callback of which will be fired when the server replies with the new privacy setting. The callback argument will be a tuple, the 2 elements @@ -1362,7 +1361,7 @@ # if lists are synchronized and updated correctly, which they # should be. If someone has a specific justified need for this # then please contact me and i'll re-enable/fix support for it. - + #def requestListGroups(self): # """ # Request (forward) list groups. @@ -1373,7 +1372,7 @@ # a dictionary mapping group IDs to group names and the # current list version. # """ - # + # # # this doesn't need to be used if syncing of the lists takes place (which it SHOULD!) # # i.e. please don't use it! # warnings.warn("Please do not use this method - use the list syncing process instead") @@ -1473,7 +1472,7 @@ the new list version (int), the group id (int) and the new group name (str). """ - + id, d = self._createIDMapping() self.sendLine("REG %s %s %s 0" % (id, groupID, quote(newName))) def _cb(r): @@ -1509,7 +1508,7 @@ version, and the group id (if relevant, otherwise it will be None) """ - + id, d = self._createIDMapping() listType = listIDToCode[listType].upper() if listType == "FL": @@ -1554,7 +1553,7 @@ version, and the group id (if relevant, otherwise it will be None) """ - + id, d = self._createIDMapping() listType = listIDToCode[listType].upper() if listType == "FL": @@ -1624,7 +1623,7 @@ After running the method the server is expected to close the connection. """ - + self.sendLine("OUT") class NotificationFactory(ClientFactory): @@ -2117,7 +2116,7 @@ self.state = 'CONNECTING' self.segmentLength = 0 self.buffer = '' - + if isinstance(file, types.StringType): path = os.path.join(directory, file) if os.path.exists(path) and not self.overwrite: @@ -2237,7 +2236,7 @@ @ivar auth: the auth cookie (number) to use when sending the transfer invitation """ - + def __init__(self, file): """ @param file: A string or file object represnting the file to send. --- twisted/words/protocols/oscar.py +++ twisted/words/protocols/oscar.py @@ -1,5 +1,5 @@ # -*- test-case-name: twisted.words.test -*- -# Copyright (c) 2001-2005 Twisted Matrix Laboratories. +# Copyright (c) 2001-2008 Twisted Matrix Laboratories. # See LICENSE for details. @@ -9,20 +9,17 @@ Maintainer: Paul Swartz """ -from __future__ import nested_scopes - -from twisted.internet import reactor, defer, protocol -from twisted.python import log - import struct -import md5 import string import socket import random -import time import types import re +from twisted.internet import reactor, defer, protocol +from twisted.python import log +from twisted.python.hashlib import md5 + def logPacketData(data): lines = len(data)/16 if lines*16 != len(data): lines=lines+1 @@ -62,9 +59,9 @@ return dict,data def encryptPasswordMD5(password,key): - m=md5.new() + m=md5() m.update(key) - m.update(md5.new(password).digest()) + m.update(md5(password).digest()) m.update("AOL Instant Messenger (SM)") return m.digest() --- twisted/words/test/test_jabberclient.py +++ twisted/words/test/test_jabberclient.py @@ -1,11 +1,11 @@ -# Copyright (c) 2001-2007 Twisted Matrix Laboratories. +# Copyright (c) 2001-2008 Twisted Matrix Laboratories. # See LICENSE for details. """ Tests for L{twisted.words.protocols.jabber.client} """ -import sha +from twisted.python.hashlib import sha1 from twisted.trial import unittest from twisted.words.protocols.jabber import client, error, jid, xmlstream from twisted.words.protocols.jabber.sasl import SASLInitiatingInitializer @@ -117,7 +117,7 @@ self.assertEquals(('jabber:iq:auth', 'query'), (iq.children[0].uri, iq.children[0].name)) self.assertEquals('user', unicode(iq.query.username)) - self.assertEquals(sha.new('12345secret').hexdigest(), + self.assertEquals(sha1('12345secret').hexdigest(), unicode(iq.query.digest)) self.assertEquals('resource', unicode(iq.query.resource)) --- twisted/words/test/test_jabbercomponent.py +++ twisted/words/test/test_jabbercomponent.py @@ -5,9 +5,8 @@ Tests for L{twisted.words.protocols.jabber.component} """ -import sha - from twisted.python import failure +from twisted.python.hashlib import sha1 from twisted.trial import unittest from twisted.words.protocols.jabber import component, xmlstream from twisted.words.protocols.jabber.jid import JID @@ -50,7 +49,7 @@ handshake = self.output[-1] self.assertEquals('handshake', handshake.name) self.assertEquals('test:component', handshake.uri) - self.assertEquals(sha.new("%s%s" % ('12345', 'secret')).hexdigest(), + self.assertEquals(sha1("%s%s" % ('12345', 'secret')).hexdigest(), unicode(handshake)) # successful authentication @@ -80,7 +79,7 @@ xs.dataReceived("<stream:stream xmlns='jabber:component:accept' xmlns:stream='http://etherx.jabber.org/streams' from='cjid' id='12345'>") # Calculate what we expect the handshake value to be - hv = sha.new("%s%s" % ("12345", "secret")).hexdigest() + hv = sha1("%s%s" % ("12345", "secret")).hexdigest() self.assertEquals(outlist[1], "<handshake>%s</handshake>" % (hv)) --- twisted/words/test/test_msn.py +++ twisted/words/test/test_msn.py @@ -1,4 +1,4 @@ -# Copyright (c) 2001-2005 Twisted Matrix Laboratories. +# Copyright (c) 2001-2008 Twisted Matrix Laboratories. # See LICENSE for details. """ @@ -6,7 +6,7 @@ """ # System imports -import StringIO, sys +import StringIO # Twisted imports @@ -24,6 +24,7 @@ from twisted.words.protocols import msn +from twisted.python.hashlib import md5 from twisted.protocols import loopback from twisted.internet.defer import Deferred from twisted.trial import unittest @@ -255,10 +256,35 @@ self._versionTest("VER 1 MSNP8\r\n") + def test_challenge(self): + """ + L{NotificationClient} responds to a I{CHL} message by sending a I{QRY} + back which included a hash based on the parameters of the I{CHL}. + """ + transport = StringIOWithoutClosing() + self.client.makeConnection(transport) + transport.seek(0) + transport.truncate() + + challenge = "15570131571988941333" + self.client.dataReceived('CHL 0 ' + challenge + '\r\n') + # md5 of the challenge and a magic string defined by the protocol + response = "8f2f5a91b72102cd28355e9fc9000d6e" + # Sanity check - the response is what the comment above says it is. + self.assertEqual( + response, md5(challenge + "Q1P7W2E4J9R8U3S5").hexdigest()) + self.assertEqual( + transport.getvalue(), + # 2 is the next transaction identifier. 32 is the length of the + # response. + "QRY 2 msmsgs@msnmsgr.com 32\r\n" + response) + + def testLogin(self): self.client.lineReceived('USR 1 OK foo@bar.com Test%20Screen%20Name 1 0') self.failUnless((self.client.state == 'LOGIN'), msg='Failed to detect successful login') + def testProfile(self): m = 'MSG Hotmail Hotmail 353\r\nMIME-Version: 1.0\r\nContent-Type: text/x-msmsgsprofile; charset=UTF-8\r\n' m += 'LoginTime: 1016941010\r\nEmailEnabled: 1\r\nMemberIdHigh: 40000\r\nMemberIdLow: -600000000\r\nlang_preference: 1033\r\n' --- twisted/words/test/test_oscar.py +++ twisted/words/test/test_oscar.py @@ -0,0 +1,24 @@ +# Copyright (c) 2008 Twisted Matrix Laboratories. +# See LICENSE for details. + +""" +Tests for L{twisted.words.protocols.oscar}. +""" + +from twisted.trial.unittest import TestCase + +from twisted.words.protocols.oscar import encryptPasswordMD5 + + +class PasswordTests(TestCase): + """ + Tests for L{encryptPasswordMD5}. + """ + def test_encryptPasswordMD5(self): + """ + L{encryptPasswordMD5} hashes the given password and key and returns a + string suitable to use to authenticate against an OSCAR server. + """ + self.assertEqual( + encryptPasswordMD5('foo', 'bar').encode('hex'), + 'd73475c370a7b18c6c20386bcf1339f2')
Locations
Projects
Search
Status Monitor
Help
OpenBuildService.org
Documentation
API Documentation
Code of Conduct
Contact
Support
@OBShq
Terms
openSUSE Build Service is sponsored by
The Open Build Service is an
openSUSE project
.
Sign Up
Log In
Places
Places
All Projects
Status Monitor