def encodingTiming(): print "#=============== END-TO-END ENCODING ==================" shortP = "hello world" prng = AESCounterPRNG() p = encodeMessage(shortP, 0, prng)[0] t = prng.getBytes(20) print "Check short payload", timeit( lambda p=p: mixminion.BuildMessage._checkPayload(p), 1000) print "Decode without uncompress", timeit( lambda p=p,t=t: decodePayload(p, t), 1000) print "Decode short payload", timeit( lambda p=p,t=t: decodePayload(p, t).getUncompressedContents(), 1000) k20 = prng.getBytes(20*1024) p = encodeMessage(k20, 0, prng)[0] t = prng.getBytes(20) print "Decode 20K payload", timeit( lambda p=p,t=t: decodePayload(p, t).getUncompressedContents(), 1000) comp = "x"*(20*1024) p = encodeMessage(comp, 0, prng)[0] t = prng.getBytes(20) def decode(p=p,t=t): try: decodePayload(p,t).getUncompressedContents() except CompressedDataTooLong: pass print "Decode overcompressed payload", timeit(decode, 1000)
def buildMessageTiming(): print "#================= BUILD MESSAGE =====================" pk = pk_generate(2048) for payload in "Hello!!!"*128, "Hello!!!"*(128*28): print "Compress %sK" % (len(payload)/1024), \ timeit(lambda p=payload: compressData(p), 100) compressed = compressData("Hello!!!"*128) print "Uncompress (1K, no max)", \ timeit(lambda c=compressed: uncompressData(c), 1000) compressed = compressData("Hello!!!"*(128*28)) print "Uncompress (28K, no max)", \ timeit(lambda c=compressed: uncompressData(c), 1000) compressed = compressData("Hello!!!"*128) print "Uncompress (1K, 1K max)", \ timeit(lambda c=compressed: uncompressData(c, 1024), 1000) compressed = compressData("Hello!!!"*(128*28)) print "Uncompress (28K, 28K max)", \ timeit(lambda c=compressed: uncompressData(c, 28<<10), 1000) payload = ("Junky qoph flags vext crwd zimb."*1024)[:22*1024] serverinfo = [FakeServerInfo("127.0.0.1", 48099, pk,"x"*20) ] * 16 def bh(np,it, serverinfo=serverinfo): ctr = AESCounterPRNG() tm = timeit_( lambda np=np,it=it,serverinfo=serverinfo,ctr=ctr: _buildHeader(serverinfo[:np], ["Z"*16]*np, 99, "Hello", ctr), it) print "Build header (%s)" %(np), timestr(tm) bh(1,100) bh(4,40) bh(8,20) bh(16,10) payload = encodeMessage(payload, 0)[0] def bm(np1,np2,it,serverinfo=serverinfo,payload=payload): tm = timeit_( \ lambda np1=np1,np2=np2,it=it,serverinfo=serverinfo, payload=payload: buildForwardPacket(payload, 500, "Hello", serverinfo[:np1], serverinfo[:np2]), it) print "Build forward message (%sx%s)" %(np1,np2), timestr(tm) bm(1,1,100) bm(8,1,40) bm(8,8,20) bm(16,16,10)
def serverProcessTiming(): print "#================= SERVER PROCESS =====================" pk = pk_generate(2048) server = FakeServerInfo("127.0.0.1", 1, pk, "X"*20) sp = PacketHandler([pk], [DummyLog()]) payload = encodeMessage("Hello world",0)[0] m_noswap = buildForwardPacket(payload, SMTP_TYPE, "f@invalid", [server, server], [server, server]) print "Server process (no swap, no log)", timeit( lambda sp=sp, m_noswap=m_noswap: sp.processPacket(m_noswap), 100) m_swap = buildForwardPacket(payload, SMTP_TYPE, "f@invalid", [server], [server, server]) print "Server process (swap, no log)", timeit( lambda sp=sp, m_swap=m_swap: sp.processPacket(m_swap), 100)
def timeEfficiency(): print "#================= ACTUAL v. IDEAL =====================" # Here we compare the time spent in an operation with the time we think # is required for its underlying operations, in order to try to measure # its efficiency. If function X is pretty efficient, there's not much # reason to try to optimize its implementation; instead, we need to attack # the functions it uses. ##### LIONESS shakey = "z"*20 aeskey = "p"*16 # Lioness_encrypt is: # 2 28K SHA1's (keyed) # 2 20b SHA1's (keyed) # 2 20b string xors. # 2 28K aes_crypts. shastr = shakey+s28K+shakey sha1_keyed_28k = timeit_((lambda shastr=shastr: _ml.sha1(shastr)), 1000) shastr = shakey+s20b+shakey sha1_keyed_20b = timeit_((lambda shastr=shastr: _ml.sha1(shastr)), 100000) strxor_20b = timeit_((lambda s=s20b: _ml.strxor(s,s)), 100000) aes_28k = timeit_((lambda s=s28K,k=aeskey: ctr_crypt(s,k)), 100) lionesskey = ("p"*20,)*4 lioness_e = timeit_((lambda s=s28K,k=lionesskey: lioness_encrypt(s,k)),100) expected = 2*(strxor_20b+aes_28k+sha1_keyed_28k+sha1_keyed_20b) print "LIONESS TOOK:", timestr(lioness_e) print " expected:", timestr(expected) print " difference:", timestr(lioness_e-expected) print " goodness: %3.2f%%" % (100*expected/lioness_e) print " breakdown: aes: %3.1f%%" % (100*2*aes_28k/lioness_e) print " long sha1: %3.1f%%" % (100*2*sha1_keyed_28k/lioness_e) print " short sha1: %3.1f%%" % (100*2*sha1_keyed_20b/lioness_e) print " short xor: %3.1f%%" % (100*2*strxor_20b/lioness_e) ##### SERVER PROCESS pk = pk_generate(2048) # Typical (no swap) server process is: # pk_decrypt (128b) # sha1 (2K-128b) #5*sha1 (16b+~16b) [HEADER_SEC,HEADER_ENC,PRNG,PAYLOAD_ENC,REPLAY] # hashlog.seen **omit # hashlog.log **omit # ctr_crypt (2K) # lioness_D (28K) # prng (128b) # lioness_D (2K) # With swap, add: # keys_from_payload=HASH(28K) # lioness_D (2K) enc = pk_encrypt(s70b, pk) rsa_128b = timeit_((lambda pk=pk,enc=enc: pk_decrypt(enc,pk)), 100) shastr = s2K[2048-128] sha1_hdr = timeit_((lambda shastr=shastr: sha1(shastr)), 10000) shastr = s64b[:32] sha1_key = timeit_((lambda shastr=shastr: sha1(shastr)), 10000) aes_2k = timeit_((lambda k=aeskey: ctr_crypt(s2K,k)), 1000) lioness_28k = lioness_e lioness_2k = timeit_(( lambda s=s2K,k=lionesskey: lioness_encrypt(s,k)),1000) prng_128b = timeit_((lambda k=aeskey: prng(k,128)),10000) server = FakeServerInfo("127.0.0.1", 1, pk, "X"*20) sp = PacketHandler([pk], [DummyLog()]) payload = encodeMessage("Hello world",0)[0] m_noswap = buildForwardPacket(payload, SMTP_TYPE, "f@invalid", [server, server], [server, server]) sp_ns = timeit_( lambda sp=sp, m_noswap=m_noswap: sp.processPacket(m_noswap), 100) expected = rsa_128b+sha1_hdr+sha1_key*5+aes_2k+lioness_28k+prng_128b expected += lioness_2k print "SERVERPROCESS TOOK:", timestr(sp_ns) print " expected:", timestr(expected) print " difference:", timestr(sp_ns-expected) print " goodness: %3.2f%%" % (100*expected/sp_ns) print " breakdown: rsa: %3.1f%%" % (100*rsa_128b/sp_ns) print " 28K lioness: %3.1f%%" % (100*lioness_28k/sp_ns) print " 2K lioness: %3.1f%%" % (100*lioness_2k/sp_ns) print " header aes: %3.1f%%" % (100*aes_2k/sp_ns) print " header sha1: %3.1f%%" % (100*sha1_hdr/sp_ns) print " keygen sha1: %3.1f%%" % (500*sha1_key/sp_ns) print " (logs not included)"