python实现的DES加密算法和3DES加密算法实例
本文实例讲述了python实现的DES加密算法和3DES加密算法。分享给大家供大家参考。具体实现方法如下:
#############################################################################
#Documentation#
#############################################################################
#Author:ToddWhiteman
#Date:16thMarch,2009
#Verion:2.0.0
#License:PublicDomain-freetodoasyouwish
#Homepage:http://twhiteman.netfirms.com/des.html
#
#ThisisapurepythonimplementationoftheDESencryptionalgorithm.
#It'spurepythontoavoidportabilityissues,sincemostDES
#implementationsareprogrammedinC(forperformancereasons).
#
#TripleDESclassisalsoimplemented,utilisingtheDESbase.TripleDES
#iseitherDES-EDE3witha24bytekey,orDES-EDE2witha16bytekey.
#
#SeetheREADME.txtthatshouldcomewiththispythonmoduleforthe
#implementationmethodsused.
#
#Thanksto:
#*DavidBroadwellforideas,commentsandsuggestions.
#*MarioWolffforpointingoutanddebuggingsometripledesCBCerrors.
#*SantiagoPalladinoforprovidingthePKCS5paddingtechnique.
#*ShayaforcorrectingthePAD_PKCS5tripledesCBCerrors.
#
"""ApurepythonimplementationoftheDESandTRIPLEDESencryptionalgorithms.
Classinitialization
--------------------
pyDes.des(key,[mode],[IV],[pad],[padmode])
pyDes.triple_des(key,[mode],[IV],[pad],[padmode])
key->Bytescontainingtheencryptionkey.8bytesforDES,16or24bytes
forTripleDES
mode->Optionalargumentforencryptiontype,canbeeither
pyDes.ECB(ElectronicCodeBook)orpyDes.CBC(CypherBlockChaining)
IV->OptionalInitialValuebytes,mustbesuppliedifusingCBCmode.
Lengthmustbe8bytes.
pad->Optionalargument,setthepadcharacter(PAD_NORMAL)touseduring
allencrypt/decrptoperationsdonewiththisinstance.
padmode->Optionalargument,setthepaddingmode(PAD_NORMALorPAD_PKCS5)
touseduringallencrypt/decrptoperationsdonewiththisinstance.
IrecommendtousePAD_PKCS5padding,asthenyouneverneedtoworryaboutany
paddingissues,asthepaddingcanberemovedunambiguouslyupondecrypting
datathatwasencryptedusingPAD_PKCS5padmode.
Commonmethods
--------------
encrypt(data,[pad],[padmode])
decrypt(data,[pad],[padmode])
data->Bytestobeencrypted/decrypted
pad->Optionalargument.OnlywhenusingpadmodeofPAD_NORMAL.For
encryption,addsthischaracterstotheendofthedatablockwhen
dataisnotamultipleof8bytes.Fordecryption,willremovethe
trailingcharactersthatmatchthispadcharacterfromthelast8
bytesoftheunencrypteddatablock.
padmode->Optionalargument,setthepaddingmode,mustbeoneofPAD_NORMAL
orPAD_PKCS5).DefaultstoPAD_NORMAL.
Example
-------
frompyDesimport*
data="Pleaseencryptmydata"
k=des("DESCRYPT",CBC,"\0\0\0\0\0\0\0\0",pad=None,padmode=PAD_PKCS5)
#ForPython3,you'llneedtousebytes,i.e.:
#data=b"Pleaseencryptmydata"
#k=des(b"DESCRYPT",CBC,b"\0\0\0\0\0\0\0\0",pad=None,padmode=PAD_PKCS5)
d=k.encrypt(data)
print"Encrypted:%r"%d
print"Decrypted:%r"%k.decrypt(d)
assertk.decrypt(d,padmode=PAD_PKCS5)==data
Seethemodulesource(pyDes.py)formoreexamplesofuse.
YoucanalsorunthepyDes.pyfilewithoutandargumentstoseeasimpletest.
Note:Thiscodewasnotwrittenforhigh-endsystemsneedingafast
implementation,butratherahandyportablesolutionwithsmallusage.
"""
importsys
#_pythonMajorVersionisusedtohandlePython2andPython3differences.
_pythonMajorVersion=sys.version_info[0]
#Modesofcrypting/cyphering
ECB=0
CBC=1
#Modesofpadding
PAD_NORMAL=1
PAD_PKCS5=2
#PAD_PKCS5:isamethodthatwillunambiguouslyremoveallpadding
#charactersafterdecryption,whenoriginallyencryptedwith
#thispaddingmode.
#ForagooddescriptionofthePKCS5paddingtechnique,see:
#http://www.faqs.org/rfcs/rfc1423.html
#Thebaseclasssharedbydesandtripledes.
class_baseDes(object):
def__init__(self,mode=ECB,IV=None,pad=None,padmode=PAD_NORMAL):
ifIV:
IV=self._guardAgainstUnicode(IV)
ifpad:
pad=self._guardAgainstUnicode(pad)
self.block_size=8
#Sanitycheckingofarguments.
ifpadandpadmode==PAD_PKCS5:
raiseValueError("CannotuseapadcharacterwithPAD_PKCS5")
ifIVandlen(IV)!=self.block_size:
raiseValueError("InvalidInitialValue(IV),mustbeamultipleof"+str(self.block_size)+"bytes")
#Setthepassedinvariables
self._mode=mode
self._iv=IV
self._padding=pad
self._padmode=padmode
defgetKey(self):
"""getKey()->bytes"""
returnself.__key
defsetKey(self,key):
"""Willsetthecryptingkeyforthisobject."""
key=self._guardAgainstUnicode(key)
self.__key=key
defgetMode(self):
"""getMode()->pyDes.ECBorpyDes.CBC"""
returnself._mode
defsetMode(self,mode):
"""Setsthetypeofcryptingmode,pyDes.ECBorpyDes.CBC"""
self._mode=mode
defgetPadding(self):
"""getPadding()->bytesoflength1.Paddingcharacter."""
returnself._padding
defsetPadding(self,pad):
"""setPadding()->bytesoflength1.Paddingcharacter."""
ifpadisnotNone:
pad=self._guardAgainstUnicode(pad)
self._padding=pad
defgetPadMode(self):
"""getPadMode()->pyDes.PAD_NORMALorpyDes.PAD_PKCS5"""
returnself._padmode
defsetPadMode(self,mode):
"""Setsthetypeofpaddingmode,pyDes.PAD_NORMALorpyDes.PAD_PKCS5"""
self._padmode=mode
defgetIV(self):
"""getIV()->bytes"""
returnself._iv
defsetIV(self,IV):
"""WillsettheInitialValue,usedinconjunctionwithCBCmode"""
ifnotIVorlen(IV)!=self.block_size:
raiseValueError("InvalidInitialValue(IV),mustbeamultipleof"+str(self.block_size)+"bytes")
IV=self._guardAgainstUnicode(IV)
self._iv=IV
def_padData(self,data,pad,padmode):
#Paddatadependingonthemode
ifpadmodeisNone:
#Getthedefaultpaddingmode.
padmode=self.getPadMode()
ifpadandpadmode==PAD_PKCS5:
raiseValueError("CannotuseapadcharacterwithPAD_PKCS5")
ifpadmode==PAD_NORMAL:
iflen(data)%self.block_size==0:
#Nopaddingrequired.
returndata
ifnotpad:
#Getthedefaultpadding.
pad=self.getPadding()
ifnotpad:
raiseValueError("Datamustbeamultipleof"+str(self.block_size)+"bytesinlength.Usepadmode=PAD_PKCS5orsetthepadcharacter.")
data+=(self.block_size-(len(data)%self.block_size))*pad
elifpadmode==PAD_PKCS5:
pad_len=8-(len(data)%self.block_size)
if_pythonMajorVersion<3:
data+=pad_len*chr(pad_len)
else:
data+=bytes([pad_len]*pad_len)
returndata
def_unpadData(self,data,pad,padmode):
#Unpaddatadependingonthemode.
ifnotdata:
returndata
ifpadandpadmode==PAD_PKCS5:
raiseValueError("CannotuseapadcharacterwithPAD_PKCS5")
ifpadmodeisNone:
#Getthedefaultpaddingmode.
padmode=self.getPadMode()
ifpadmode==PAD_NORMAL:
ifnotpad:
#Getthedefaultpadding.
pad=self.getPadding()
ifpad:
data=data[:-self.block_size]+\
data[-self.block_size:].rstrip(pad)
elifpadmode==PAD_PKCS5:
if_pythonMajorVersion<3:
pad_len=ord(data[-1])
else:
pad_len=data[-1]
data=data[:-pad_len]
returndata
def_guardAgainstUnicode(self,data):
#Onlyacceptbytestringsorasciiunicodevalues,otherwise
#thereisnowaytocorrectlydecodethedataintobytes.
if_pythonMajorVersion<3:
ifisinstance(data,unicode):
raiseValueError("pyDescanonlyworkwithbytes,notUnicodestrings.")
else:
ifisinstance(data,str):
#Onlyacceptasciiunicodevalues.
try:
returndata.encode('ascii')
exceptUnicodeEncodeError:
pass
raiseValueError("pyDescanonlyworkwithencodedstrings,notUnicode.")
returndata
#############################################################################
#DES#
#############################################################################
classdes(_baseDes):
"""DESencryption/decrytpionclass
SupportsECB(ElectronicCodeBook)andCBC(CypherBlockChaining)modes.
pyDes.des(key,[mode],[IV])
key->Bytescontainingtheencryptionkey,mustbeexactly8bytes
mode->Optionalargumentforencryptiontype,canbeeitherpyDes.ECB
(ElectronicCodeBook),pyDes.CBC(CypherBlockChaining)
IV->OptionalInitialValuebytes,mustbesuppliedifusingCBCmode.
Mustbe8bytesinlength.
pad->Optionalargument,setthepadcharacter(PAD_NORMAL)touse
duringallencrypt/decrptoperationsdonewiththisinstance.
padmode->Optionalargument,setthepaddingmode(PAD_NORMALor
PAD_PKCS5)touseduringallencrypt/decrptoperationsdone
withthisinstance.
"""
#PermutationandtranslationtablesforDES
__pc1=[56,48,40,32,24,16,8,
,57,49,41,33,25,17,
,1,58,50,42,34,26,
,10,2,59,51,43,35,
,54,46,38,30,22,14,
,61,53,45,37,29,21,
,5,60,52,44,36,28,
,12,4,27,19,11,3
]
#numberleftrotationsofpc1
__left_rotations=[
,1,2,2,2,2,2,2,1,2,2,2,2,2,2,1
]
#permutedchoicekey(table2)
__pc2=[
,16,10,23,0,4,
,27,14,5,20,9,
,18,11,3,25,7,
,6,26,19,12,1,
,51,30,36,46,54,
,39,50,44,32,47,
,48,38,55,33,52,
,41,49,35,28,31
]
#initialpermutationIP
__ip=[57,49,41,33,25,17,9,1,
,51,43,35,27,19,11,3,
,53,45,37,29,21,13,5,
,55,47,39,31,23,15,7,
,48,40,32,24,16,8,0,
,50,42,34,26,18,10,2,
,52,44,36,28,20,12,4,
,54,46,38,30,22,14,6
]
#Expansiontableforturning32bitblocksinto48bits
__expansion_table=[
,0,1,2,3,4,
,4,5,6,7,8,
,8,9,10,11,12,
,12,13,14,15,16,
,16,17,18,19,20,
,20,21,22,23,24,
,24,25,26,27,28,
,28,29,30,31,0
]
#The(in)famousS-boxes
__sbox=[
#S1
[14,4,13,1,2,15,11,8,3,10,6,12,5,9,0,7,
,15,7,4,14,2,13,1,10,6,12,11,9,5,3,8,
,1,14,8,13,6,2,11,15,12,9,7,3,10,5,0,
,12,8,2,4,9,1,7,5,11,3,14,10,0,6,13],
#S2
[15,1,8,14,6,11,3,4,9,7,2,13,12,0,5,10,
,13,4,7,15,2,8,14,12,0,1,10,6,9,11,5,
,14,7,11,10,4,13,1,5,8,12,6,9,3,2,15,
,8,10,1,3,15,4,2,11,6,7,12,0,5,14,9],
#S3
[10,0,9,14,6,3,15,5,1,13,12,7,11,4,2,8,
,7,0,9,3,4,6,10,2,8,5,14,12,11,15,1,
,6,4,9,8,15,3,0,11,1,2,12,5,10,14,7,
,10,13,0,6,9,8,7,4,15,14,3,11,5,2,12],
#S4
[7,13,14,3,0,6,9,10,1,2,8,5,11,12,4,15,
,8,11,5,6,15,0,3,4,7,2,12,1,10,14,9,
,6,9,0,12,11,7,13,15,1,3,14,5,2,8,4,
,15,0,6,10,1,13,8,9,4,5,11,12,7,2,14],
#S5
[2,12,4,1,7,10,11,6,8,5,3,15,13,0,14,9,
,11,2,12,4,7,13,1,5,0,15,10,3,9,8,6,
,2,1,11,10,13,7,8,15,9,12,5,6,3,0,14,
,8,12,7,1,14,2,13,6,15,0,9,10,4,5,3],
#S6
[12,1,10,15,9,2,6,8,0,13,3,4,14,7,5,11,
,15,4,2,7,12,9,5,6,1,13,14,0,11,3,8,
,14,15,5,2,8,12,3,7,0,4,10,1,13,11,6,
,3,2,12,9,5,15,10,11,14,1,7,6,0,8,13],
#S7
[4,11,2,14,15,0,8,13,3,12,9,7,5,10,6,1,
,0,11,7,4,9,1,10,14,3,5,12,2,15,8,6,
,4,11,13,12,3,7,14,10,15,6,8,0,5,9,2,
,11,13,8,1,4,10,7,9,5,0,15,14,2,3,12],
#S8
[13,2,8,4,6,15,11,1,10,9,3,14,5,0,12,7,
,15,13,8,10,3,7,4,12,5,6,11,0,14,9,2,
,11,4,1,9,12,14,2,0,6,10,13,15,3,5,8,
,1,14,7,4,10,8,13,15,12,9,0,3,5,6,11],
]
#32-bitpermutationfunctionPusedontheoutputoftheS-boxes
__p=[
,6,19,20,28,11,
,16,0,14,22,25,
,17,30,9,1,7,
,13,31,26,2,8,
,12,29,5,21,10,
,24
]
#finalpermutationIP^-1
__fp=[
,7,47,15,55,23,63,31,
,6,46,14,54,22,62,30,
,5,45,13,53,21,61,29,
,4,44,12,52,20,60,28,
,3,43,11,51,19,59,27,
,2,42,10,50,18,58,26,
,1,41,9,49,17,57,25,
,0,40,8,48,16,56,24
]
#Typeofcryptingbeingdone
ENCRYPT=0x00
DECRYPT=0x01
#Initialisation
def__init__(self,key,mode=ECB,IV=None,pad=None,padmode=PAD_NORMAL):
#Sanitycheckingofarguments.
iflen(key)!=8:
raiseValueError("InvalidDESkeysize.Keymustbeexactly8byteslong.")
_baseDes.__init__(self,mode,IV,pad,padmode)
self.key_size=8
self.L=[]
self.R=[]
self.Kn=[[0]*48]*16#1648-bitkeys(K1-K16)
self.final=[]
self.setKey(key)
defsetKey(self,key):
"""Willsetthecryptingkeyforthisobject.Mustbe8bytes."""
_baseDes.setKey(self,key)
self.__create_sub_keys()
def__String_to_BitList(self,data):
"""Turnthestringdata,intoalistofbits(1,0)'s"""
if_pythonMajorVersion<3:
#Turnthestringsintointegers.Python3usesabytes
#class,whichalreadyhasthisbehaviour.
data=[ord(c)forcindata]
l=len(data)*8
result=[0]*l
pos=0
forchindata:
i=7
whilei>=0:
ifch&(1<<i)!=0:
result[pos]=1
else:
result[pos]=0
pos+=1
i-=1
returnresult
def__BitList_to_String(self,data):
"""Turnthelistofbits->data,intoastring"""
result=[]
pos=0
c=0
whilepos<len(data):
c+=data[pos]<<(7-(pos%8))
if(pos%8)==7:
result.append(c)
c=0
pos+=1
if_pythonMajorVersion<3:
return''.join([chr(c)forcinresult])
else:
returnbytes(result)
def__permutate(self,table,block):
"""Permutatethisblockwiththespecifiedtable"""
returnlist(map(lambdax:block[x],table))
#Transformthesecretkey,sothatitisreadyfordataprocessing
#Createthe16subkeys,K[1]-K[16]
def__create_sub_keys(self):
"""Createthe16subkeysK[1]toK[16]fromthegivenkey"""
key=self.__permutate(des.__pc1,self.__String_to_BitList(self.getKey()))
i=0
#SplitintoLeftandRightsections
self.L=key[:28]
self.R=key[28:]
whilei<16:
j=0
#Performcircularleftshifts
whilej<des.__left_rotations[i]:
self.L.append(self.L[0])
delself.L[0]
self.R.append(self.R[0])
delself.R[0]
j+=1
#Createoneofthe16subkeysthroughpc2permutation
self.Kn[i]=self.__permutate(des.__pc2,self.L+self.R)
i+=1
#Mainpartoftheencryptionalgorithm,thenumbercruncher:)
def__des_crypt(self,block,crypt_type):
"""CrypttheblockofdatathroughDESbit-manipulation"""
block=self.__permutate(des.__ip,block)
self.L=block[:32]
self.R=block[32:]
#EncryptionstartsfromKn[1]throughtoKn[16]
ifcrypt_type==des.ENCRYPT:
iteration=0
iteration_adjustment=1
#DecryptionstartsfromKn[16]downtoKn[1]
else:
iteration=15
iteration_adjustment=-1
i=0
whilei<16:
#MakeacopyofR[i-1],thiswilllaterbecomeL[i]
tempR=self.R[:]
#PermutateR[i-1]tostartcreatingR[i]
self.R=self.__permutate(des.__expansion_table,self.R)
#ExclusiveorR[i-1]withK[i],createB[1]toB[8]whilsthere
self.R=list(map(lambdax,y:x^y,self.R,self.Kn[iteration]))
B=[self.R[:6],self.R[6:12],self.R[12:18],self.R[18:24],self.R[24:30],self.R[30:36],self.R[36:42],self.R[42:]]
#Optimization:Replacedbelowcommentedcodewithabove
#j=0
#B=[]
#whilej<len(self.R):
#self.R[j]=self.R[j]^self.Kn[iteration][j]
#j+=1
#ifj%6==0:
#B.append(self.R[j-6:j])
#PermutateB[1]toB[8]usingtheS-Boxes
j=0
Bn=[0]*32
pos=0
whilej<8:
#Workouttheoffsets
m=(B[j][0]<<1)+B[j][5]
n=(B[j][1]<<3)+(B[j][2]<<2)+(B[j][3]<<1)+B[j][4]
#Findthepermutationvalue
v=des.__sbox[j][(m<<4)+n]
#Turnvalueintobits,addittoresult:Bn
Bn[pos]=(v&8)>>3
Bn[pos+1]=(v&4)>>2
Bn[pos+2]=(v&2)>>1
Bn[pos+3]=v&1
pos+=4
j+=1
#PermutatetheconcatinationofB[1]toB[8](Bn)
self.R=self.__permutate(des.__p,Bn)
#XorwithL[i-1]
self.R=list(map(lambdax,y:x^y,self.R,self.L))
#Optimization:Thisnowreplacesthebelowcommentedcode
#j=0
#whilej<len(self.R):
#self.R[j]=self.R[j]^self.L[j]
#j+=1
#L[i]becomesR[i-1]
self.L=tempR
i+=1
iteration+=iteration_adjustment
#FinalpermutationofR[16]L[16]
self.final=self.__permutate(des.__fp,self.R+self.L)
returnself.final
#Datatobeencrypted/decrypted
defcrypt(self,data,crypt_type):
"""Cryptthedatainblocks,runningitthroughdes_crypt()"""
#Errorcheckthedata
ifnotdata:
return''
iflen(data)%self.block_size!=0:
ifcrypt_type==des.DECRYPT:#Decryptionmustworkon8byteblocks
raiseValueError("Invaliddatalength,datamustbeamultipleof"+str(self.block_size)+"bytes\n.")
ifnotself.getPadding():
raiseValueError("Invaliddatalength,datamustbeamultipleof"+str(self.block_size)+"bytes\n.Trysettingtheoptionalpaddingcharacter")
else:
data+=(self.block_size-(len(data)%self.block_size))*self.getPadding()
#print"Lenofdata:%f"%(len(data)/self.block_size)
ifself.getMode()==CBC:
ifself.getIV():
iv=self.__String_to_BitList(self.getIV())
else:
raiseValueError("ForCBCmode,youmustsupplytheInitialValue(IV)forciphering")
#Splitthedataintoblocks,cryptingeachoneseperately
i=0
dict={}
result=[]
#cached=0
#lines=0
whilei<len(data):
#Testcodeforcachingencryptionresults
#lines+=1
#ifdict.has_key(data[i:i+8]):
#print"Cachedresultfor:%s"%data[i:i+8]
#cached+=1
#result.append(dict[data[i:i+8]])
#i+=8
#continue
block=self.__String_to_BitList(data[i:i+8])
#XorwithIVifusingCBCmode
ifself.getMode()==CBC:
ifcrypt_type==des.ENCRYPT:
block=list(map(lambdax,y:x^y,block,iv))
#j=0
#whilej<len(block):
#block[j]=block[j]^iv[j]
#j+=1
processed_block=self.__des_crypt(block,crypt_type)
ifcrypt_type==des.DECRYPT:
processed_block=list(map(lambdax,y:x^y,processed_block,iv))
#j=0
#whilej<len(processed_block):
#processed_block[j]=processed_block[j]^iv[j]
#j+=1
iv=block
else:
iv=processed_block
else:
processed_block=self.__des_crypt(block,crypt_type)
#Addtheresultingcryptedblocktoourlist
#d=self.__BitList_to_String(processed_block)
#result.append(d)
result.append(self.__BitList_to_String(processed_block))
#dict[data[i:i+8]]=d
i+=8
#print"Lines:%d,cached:%d"%(lines,cached)
#Returnthefullcryptedstring
if_pythonMajorVersion<3:
return''.join(result)
else:
returnbytes.fromhex('').join(result)
defencrypt(self,data,pad=None,padmode=None):
"""encrypt(data,[pad],[padmode])->bytes
data:Bytestobeencrypted
pad:Optionalargumentforencryptionpadding.Mustonlybeonebyte
padmode:Optionalargumentforoverridingthepaddingmode.
Thedatamustbeamultipleof8bytesandwillbeencrypted
withthealreadyspecifiedkey.Datadoesnothavetobea
multipleof8bytesifthepaddingcharacterissupplied,or
thepadmodeissettoPAD_PKCS5,asbyteswillthenaddedto
ensurethebepaddeddataisamultipleof8bytes.
"""
data=self._guardAgainstUnicode(data)
ifpadisnotNone:
pad=self._guardAgainstUnicode(pad)
data=self._padData(data,pad,padmode)
returnself.crypt(data,des.ENCRYPT)
defdecrypt(self,data,pad=None,padmode=None):
"""decrypt(data,[pad],[padmode])->bytes
data:Bytestobeencrypted
pad:Optionalargumentfordecryptionpadding.Mustonlybeonebyte
padmode:Optionalargumentforoverridingthepaddingmode.
Thedatamustbeamultipleof8bytesandwillbedecrypted
withthealreadyspecifiedkey.InPAD_NORMALmode,ifthe
optionalpaddingcharacterissupplied,thentheun-encrypted
datawillhavethepaddingcharactersremovedfromtheendof
thebytes.Thispadremovalonlyoccursonthelast8bytesof
thedata(lastdatablock).InPAD_PKCS5mode,thespecial
paddingendmarkerswillberemovedfromthedataafterdecrypting.
"""
data=self._guardAgainstUnicode(data)
ifpadisnotNone:
pad=self._guardAgainstUnicode(pad)
data=self.crypt(data,des.DECRYPT)
returnself._unpadData(data,pad,padmode)
#############################################################################
#TripleDES#
#############################################################################
classtriple_des(_baseDes):
"""TripleDESencryption/decrytpionclass
ThisalgorithmusestheDES-EDE3(whena24bytekeyissupplied)or
theDES-EDE2(whena16bytekeyissupplied)encryptionmethods.
SupportsECB(ElectronicCodeBook)andCBC(CypherBlockChaining)modes.
pyDes.des(key,[mode],[IV])
key->Bytescontainingtheencryptionkey,mustbeeither16or
byteslong
mode->Optionalargumentforencryptiontype,canbeeitherpyDes.ECB
(ElectronicCodeBook),pyDes.CBC(CypherBlockChaining)
IV->OptionalInitialValuebytes,mustbesuppliedifusingCBCmode.
Mustbe8bytesinlength.
pad->Optionalargument,setthepadcharacter(PAD_NORMAL)touse
duringallencrypt/decrptoperationsdonewiththisinstance.
padmode->Optionalargument,setthepaddingmode(PAD_NORMALor
PAD_PKCS5)touseduringallencrypt/decrptoperationsdone
withthisinstance.
"""
def__init__(self,key,mode=ECB,IV=None,pad=None,padmode=PAD_NORMAL):
_baseDes.__init__(self,mode,IV,pad,padmode)
self.setKey(key)
defsetKey(self,key):
"""Willsetthecryptingkeyforthisobject.Either16or24byteslong."""
self.key_size=24#UseDES-EDE3mode
iflen(key)!=self.key_size:
iflen(key)==16:#UseDES-EDE2mode
self.key_size=16
else:
raiseValueError("InvalidtripleDESkeysize.Keymustbeeither16or24byteslong")
ifself.getMode()==CBC:
ifnotself.getIV():
#Usethefirst8bytesofthekey
self._iv=key[:self.block_size]
iflen(self.getIV())!=self.block_size:
raiseValueError("InvalidIV,mustbe8bytesinlength")
self.__key1=des(key[:8],self._mode,self._iv,
self._padding,self._padmode)
self.__key2=des(key[8:16],self._mode,self._iv,
self._padding,self._padmode)
ifself.key_size==16:
self.__key3=self.__key1
else:
self.__key3=des(key[16:],self._mode,self._iv,
self._padding,self._padmode)
_baseDes.setKey(self,key)
#Overridesettermethodstoworkonall3keys.
defsetMode(self,mode):
"""Setsthetypeofcryptingmode,pyDes.ECBorpyDes.CBC"""
_baseDes.setMode(self,mode)
forkeyin(self.__key1,self.__key2,self.__key3):
key.setMode(mode)
defsetPadding(self,pad):
"""setPadding()->bytesoflength1.Paddingcharacter."""
_baseDes.setPadding(self,pad)
forkeyin(self.__key1,self.__key2,self.__key3):
key.setPadding(pad)
defsetPadMode(self,mode):
"""Setsthetypeofpaddingmode,pyDes.PAD_NORMALorpyDes.PAD_PKCS5"""
_baseDes.setPadMode(self,mode)
forkeyin(self.__key1,self.__key2,self.__key3):
key.setPadMode(mode)
defsetIV(self,IV):
"""WillsettheInitialValue,usedinconjunctionwithCBCmode"""
_baseDes.setIV(self,IV)
forkeyin(self.__key1,self.__key2,self.__key3):
key.setIV(IV)
defencrypt(self,data,pad=None,padmode=None):
"""encrypt(data,[pad],[padmode])->bytes
data:bytestobeencrypted
pad:Optionalargumentforencryptionpadding.Mustonlybeonebyte
padmode:Optionalargumentforoverridingthepaddingmode.
Thedatamustbeamultipleof8bytesandwillbeencrypted
withthealreadyspecifiedkey.Datadoesnothavetobea
multipleof8bytesifthepaddingcharacterissupplied,or
thepadmodeissettoPAD_PKCS5,asbyteswillthenaddedto
ensurethebepaddeddataisamultipleof8bytes.
"""
ENCRYPT=des.ENCRYPT
DECRYPT=des.DECRYPT
data=self._guardAgainstUnicode(data)
ifpadisnotNone:
pad=self._guardAgainstUnicode(pad)
#Padthedataaccordingly.
data=self._padData(data,pad,padmode)
ifself.getMode()==CBC:
self.__key1.setIV(self.getIV())
self.__key2.setIV(self.getIV())
self.__key3.setIV(self.getIV())
i=0
result=[]
whilei<len(data):
block=self.__key1.crypt(data[i:i+8],ENCRYPT)
block=self.__key2.crypt(block,DECRYPT)
block=self.__key3.crypt(block,ENCRYPT)
self.__key1.setIV(block)
self.__key2.setIV(block)
self.__key3.setIV(block)
result.append(block)
i+=8
if_pythonMajorVersion<3:
return''.join(result)
else:
returnbytes.fromhex('').join(result)
else:
data=self.__key1.crypt(data,ENCRYPT)
data=self.__key2.crypt(data,DECRYPT)
returnself.__key3.crypt(data,ENCRYPT)
defdecrypt(self,data,pad=None,padmode=None):
"""decrypt(data,[pad],[padmode])->bytes
data:bytestobeencrypted
pad:Optionalargumentfordecryptionpadding.Mustonlybeonebyte
padmode:Optionalargumentforoverridingthepaddingmode.
Thedatamustbeamultipleof8bytesandwillbedecrypted
withthealreadyspecifiedkey.InPAD_NORMALmode,ifthe
optionalpaddingcharacterissupplied,thentheun-encrypted
datawillhavethepaddingcharactersremovedfromtheendof
thebytes.Thispadremovalonlyoccursonthelast8bytesof
thedata(lastdatablock).InPAD_PKCS5mode,thespecial
paddingendmarkerswillberemovedfromthedataafter
decrypting,nopadcharacterisrequiredforPAD_PKCS5.
"""
ENCRYPT=des.ENCRYPT
DECRYPT=des.DECRYPT
data=self._guardAgainstUnicode(data)
ifpadisnotNone:
pad=self._guardAgainstUnicode(pad)
ifself.getMode()==CBC:
self.__key1.setIV(self.getIV())
self.__key2.setIV(self.getIV())
self.__key3.setIV(self.getIV())
i=0
result=[]
whilei<len(data):
iv=data[i:i+8]
block=self.__key3.crypt(iv,DECRYPT)
block=self.__key2.crypt(block,ENCRYPT)
block=self.__key1.crypt(block,DECRYPT)
self.__key1.setIV(iv)
self.__key2.setIV(iv)
self.__key3.setIV(iv)
result.append(block)
i+=8
if_pythonMajorVersion<3:
data=''.join(result)
else:
data=bytes.fromhex('').join(result)
else:
data=self.__key3.crypt(data,DECRYPT)
data=self.__key2.crypt(data,ENCRYPT)
data=self.__key1.crypt(data,DECRYPT)
returnself._unpadData(data,pad,padmode)
希望本文所述对大家的Python程序设计有所帮助。