Beispiel #1
0
def _check_oaep_padding(data, p, b):
    '''Checks the OAEP padding on a 'bytes'-byte string.'''
    if len(data) != b:
        raise CryptoError("Decoding error")

    # This test (though required in the OAEP spec) is extraneous here.
    # if len(data) < 2*DIGEST_LEN+1:
    #    raise CryptoError("Decoding error")

    if data[0] != '\x00':
        raise CryptoError("Decoding error")
    maskedSeed, maskedDB = data[1:DIGEST_LEN + 1], data[DIGEST_LEN + 1:]
    seed = _ml.strxor(maskedSeed, _oaep_mgf(maskedDB, DIGEST_LEN))
    db = _ml.strxor(maskedDB, _oaep_mgf(seed, len(maskedDB)))
    m = None

    if db[:DIGEST_LEN] != _ml.sha1(p):
        raise CryptoError("Decoding error")

    for i in xrange(DIGEST_LEN, len(db)):
        if db[i] == '\x01':
            m = db[i + 1:]
            break
        elif db[i] == '\x00':
            pass
        else:
            raise CryptoError("Decoding error")
    if m is None:
        raise CryptoError("Decoding error")
    return m
Beispiel #2
0
def _check_oaep_padding(data, p, bytes):
    """Checks the OAEP padding on a 'bytes'-byte string."""
    if len(data) != bytes:
        raise CryptoError("Decoding error")

    # This test (though required in the OAEP spec) is extraneous here.
    # if len(data) < 2*DIGEST_LEN+1:
    #    raise CryptoError("Decoding error")

    if data[0] != "\x00":
        raise CryptoError("Decoding error")
    maskedSeed, maskedDB = data[1 : DIGEST_LEN + 1], data[DIGEST_LEN + 1 :]
    seed = _ml.strxor(maskedSeed, _oaep_mgf(maskedDB, DIGEST_LEN))
    db = _ml.strxor(maskedDB, _oaep_mgf(seed, len(maskedDB)))
    m = None

    if db[:DIGEST_LEN] != _ml.sha1(p):
        raise CryptoError("Decoding error")

    for i in xrange(DIGEST_LEN, len(db)):
        if db[i] == "\x01":
            m = db[i + 1 :]
            break
        elif db[i] == "\x00":
            pass
        else:
            raise CryptoError("Decoding error")
    if m is None:
        raise CryptoError("Decoding error")
    return m
Beispiel #3
0
 def getLionessKeys(self, mode):
     """Returns a set of 4 lioness keys, as described in the Mixminion
        specification."""
     z19 = "\x00" * 19
     key1 = sha1(self.master + mode)
     key2 = _ml.strxor(key1, z19 + "\x01")
     key3 = _ml.strxor(key1, z19 + "\x02")
     key4 = _ml.strxor(key1, z19 + "\x03")
     return (key1, key2, key3, key4)
Beispiel #4
0
 def getLionessKeys(self, mode):
     """Returns a set of 4 lioness keys, as described in the Mixminion
        specification."""
     z19 = "\x00" * 19
     key1 = sha1(self.master+mode)
     key2 = _ml.strxor(key1, z19 + "\x01")
     key3 = _ml.strxor(key1, z19 + "\x02")
     key4 = _ml.strxor(key1, z19 + "\x03")
     return (key1, key2, key3, key4)
Beispiel #5
0
def _add_oaep_padding(data, p, bytes, rng=None):
    """Add oaep padding suitable for a 'bytes'-byte key, using 'p' as a
       security parameter and 'rng' as a random number generator.

       If rng is None, uses the general purpose RNG.  The parameter may
       be any length.  len(data) must be <= bytes-42.  """
    if rng is None:
        rng = getCommonPRNG()
    bytes = bytes - 1
    mLen = len(data)
    paddingLen = bytes - mLen - 2 * DIGEST_LEN - 1
    if paddingLen < 0:
        raise CryptoError("Message too long")
    db = "%s%s\x01%s" % (sha1(p), "\x00" * paddingLen, data)
    seed = rng.getBytes(DIGEST_LEN)
    maskedDB = _ml.strxor(db, _oaep_mgf(seed, bytes - DIGEST_LEN))
    maskedSeed = _ml.strxor(seed, _oaep_mgf(maskedDB, DIGEST_LEN))
    return "\x00%s%s" % (maskedSeed, maskedDB)
Beispiel #6
0
def _add_oaep_padding(data, p, b, rng=None):
    '''Add oaep padding suitable for a 'bytes'-byte key, using 'p' as a
       security parameter and 'rng' as a random number generator.

       If rng is None, uses the general purpose RNG.  The parameter may
       be any length.  len(data) must be <= bytes-42.  '''
    if rng is None:
        rng = getCommonPRNG()
    b = b - 1
    mLen = len(data)
    paddingLen = b - mLen - 2 * DIGEST_LEN - 1
    if paddingLen < 0:
        raise CryptoError("Message too long")
    db = "%s%s\x01%s" % (sha1(p), "\x00" * paddingLen, data)
    seed = rng.getBytes(DIGEST_LEN)
    maskedDB = _ml.strxor(db, _oaep_mgf(seed, b - DIGEST_LEN))
    maskedSeed = _ml.strxor(seed, _oaep_mgf(maskedDB, DIGEST_LEN))
    return '\x00%s%s' % (maskedSeed, maskedDB)
Beispiel #7
0
def testLeaks1():
    print "Trying to leak (sha1,aes,xor,seed,oaep)"
    s20k="a"*20*1024
    keytxt="a"*16
    key = _ml.aes_key(keytxt)
    while 1:
        _ml.aes_key(keytxt)
        _ml.sha1(s20k)
        _ml.aes_ctr128_crypt(key,s20k,0)
        _ml.aes_ctr128_crypt(key,s20k,2000)
        _ml.aes_ctr128_crypt(key,"",2000,20000)
        _ml.aes_ctr128_crypt(key,"",0,20000)
        _ml.aes_ctr128_crypt(key,s20k,0,2000)
        try:
            _ml.aes_ctr128_crypt("abc",s20k,0,2000)
        except:
            pass
        _ml.strxor(s20k,s20k)
        try:
            _ml.strxor(s20k,keytxt)
        except:
            pass
        _ml.openssl_seed(s20k)
        r = _ml.add_oaep_padding("Hello",OAEP_PARAMETER,128)
        _ml.check_oaep_padding(r,OAEP_PARAMETER,128)
        try:
            _ml.check_oaep_padding("hello",OAEP_PARAMETER,128)
        except:
            pass
        try:
            _ml.add_oaep_padding(s20k,OAEP_PARAMETER,128)
        except:
            pass
        try:
            _ml.add_oaep_padding("a"*127,OAEP_PARAMETER,128)
        except:
            pass
Beispiel #8
0
def strxor(s1, s2):
    """Computes the bitwise xor of two strings.  Raises an exception if the
       strings' lengths are unequal.
    """
    return _ml.strxor(s1, s2)
Beispiel #9
0
 def getBearKeys(self, mode):
     z19 = "\x00" * 19
     key1 = sha1(self.master + mode)
     key2 = _ml.strxor(key1, z19 + "\x01")
     return (key1, key2)
Beispiel #10
0
       super-pseudorandom permutation.
    """

    assert len(key1) == len(key3) == DIGEST_LEN
    assert len(key2) == len(key4) == DIGEST_LEN
    assert len(s) > DIGEST_LEN

    # Split the message.
    left = s[:DIGEST_LEN]
    right = s[DIGEST_LEN:]
    del s
    # Performance note: This business with sha1("".join((key,right,key)))
    # may look slow, but it contributes only .7% to the total time for
    # LIONESS.
    right = _ml.aes_ctr128_crypt(_ml.aes_key(_ml.sha1("".join((key1, left, key1)))[:AES_KEY_LEN]), right, 0)
    left = _ml.strxor(left, _ml.sha1("".join((key2, right, key2))))
    right = _ml.aes_ctr128_crypt(_ml.aes_key(_ml.sha1("".join((key3, left, key3)))[:AES_KEY_LEN]), right, 0)
    left = _ml.strxor(left, _ml.sha1("".join((key4, right, key4))))

    # You could write the above as:
    #   right = ctr_crypt(right, "".join((key1,left,key1))[:AES_KEY_LEN])
    #   left = strxor(left, sha1("".join((key2,right,key2))))
    #   right = ctr_crypt(right, "".join((key3,left,key3))[:AES_KEY_LEN])
    #   left = strxor(left, sha1("".join((key4,right,key4))))
    # but that would be slower by about 10%.  (Since LIONESS is in the
    # critical path, we care.)

    return left + right


def lioness_decrypt(s, (key1, key2, key3, key4)):
Beispiel #11
0
def strxor(s1, s2):
    """Computes the bitwise xor of two strings.  Raises an exception if the
       strings' lengths are unequal.
    """
    return _ml.strxor(s1, s2)
Beispiel #12
0
 def getBearKeys(self, mode):
     z19 = "\x00" * 19
     key1 = sha1(self.master + mode)
     key2 = _ml.strxor(key1, z19 + "\x01")
     return (key1, key2)
Beispiel #13
0
    assert len(key1) == len(key3) == DIGEST_LEN
    assert len(key2) == len(key4) == DIGEST_LEN
    assert len(s) > DIGEST_LEN

    # Split the message.
    left = s[:DIGEST_LEN]
    right = s[DIGEST_LEN:]
    del s
    # Performance note: This business with sha1("".join((key,right,key)))
    # may look slow, but it contributes only .7% to the total time for
    # LIONESS.
    right = _ml.aes_ctr128_crypt(
        _ml.aes_key(_ml.sha1("".join((key1, left, key1)))[:AES_KEY_LEN]),
        right, 0)
    left = _ml.strxor(left, _ml.sha1("".join((key2, right, key2))))
    right = _ml.aes_ctr128_crypt(
        _ml.aes_key(_ml.sha1("".join((key3, left, key3)))[:AES_KEY_LEN]),
        right, 0)
    left = _ml.strxor(left, _ml.sha1("".join((key4, right, key4))))

    # You could write the above as:
    #   right = ctr_crypt(right, "".join((key1,left,key1))[:AES_KEY_LEN])
    #   left = strxor(left, sha1("".join((key2,right,key2))))
    #   right = ctr_crypt(right, "".join((key3,left,key3))[:AES_KEY_LEN])
    #   left = strxor(left, sha1("".join((key4,right,key4))))
    # but that would be slower by about 10%.  (Since LIONESS is in the
    # critical path, we care.)
    return left + right

Beispiel #14
0
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)"
Beispiel #15
0
def cryptoTiming():
    print "#==================== CRYPTO ======================="

    print "SHA1 (short)", timeit((lambda: sha1(short)), 100000)
    print "SHA1 (64b)", timeit((lambda: sha1(s64b)), 100000)
    print "SHA1 (2K)", timeit((lambda: sha1(s2K)), 10000)
    print "SHA1 (8K)", timeit((lambda: sha1(s8K)), 10000)
    print "SHA1 (28K)", timeit((lambda: sha1(s28K)), 1000)
    print "SHA1 (32K)", timeit((lambda: sha1(s32K)), 1000)

    shakey = "8charstr"*2
    print "Keyed SHA1 for lioness (28K, unoptimized)", timeit(
        (lambda shakey=shakey: _ml.sha1("".join((shakey,s28K,shakey)))), 1000)

    print "TRNG (20 byte)", timeit((lambda: trng(20)), 100)
    print "TRNG (128 byte)", timeit((lambda: trng(128)), 100)
    print "TRNG (1K)", timeit((lambda: trng(1024)), 100)

    print "xor (1K)", timeit((lambda: _ml.strxor(s1K,s1K)), 100000)
    print "xor (32K)", timeit((lambda: _ml.strxor(s32K,s32K)), 1000)

    key = "8charstr"*2
    print "aes (short)", timeit((lambda key=key: ctr_crypt(short,key)), 100000)
    print "aes (1K)", timeit((lambda key=key: ctr_crypt(s1K,key)), 10000)
    print "aes (2K)", timeit((lambda key=key: ctr_crypt(s2K,key)), 10000)
    print "aes (28K)", timeit((lambda key=key: ctr_crypt(s28K,key)), 100)
    print "aes (32K)", timeit((lambda key=key: ctr_crypt(s32K,key)), 100)

    key = _ml.aes_key(key)
    print "aes (short,pre-key)", \
          timeit((lambda key=key: ctr_crypt(short,key)), 100000)
    print "aes (1K,pre-key)", \
          timeit((lambda key=key: ctr_crypt(s1K,key)), 10000)
    print "aes (28K,pre-key)", \
          timeit((lambda key=key: ctr_crypt(s28K,key)), 100)
    print "aes (32K,pre-key)", \
          timeit((lambda key=key: ctr_crypt(s32K,key)), 100)

    print "aes (32K,pre-key,unoptimized)", timeit(
        (lambda key=key: _ml.strxor(prng(key,32768),s32K)), 100)

    print "prng (short)", timeit((lambda key=key: prng(key,8)), 100000)
    print "prng (128b)", timeit((
        lambda key=key: prng(key,18)), 10000)
    print "prng (1K)", timeit((
        lambda key=key: prng(key,1024)), 10000)
    print "prng (2K)", timeit((
        lambda key=key: prng(key,2048)), 10000)
    print "prng (28K)", timeit((
        lambda key=key: prng(key,28678)), 100)
    print "prng (32K)", timeit((lambda key=key: prng(key,32768)), 100)
    print "prng (32K, unoptimized)", timeit(
        (lambda key=key: ctr_crypt('\x00'*32768, key)), 100)

    c = AESCounterPRNG()
    print "aesprng.getInt (10)", \
          timeit((lambda c=c: c.getInt(10)), 10000)
    print "aesprng.getInt (1000)", \
          timeit((lambda c=c: c.getInt(1000)), 10000)
    print "aesprng.getInt (513)", \
          timeit((lambda c=c: c.getInt(513)), 10000)

    L10 = [ "x" ] * 10
    L1000 = [ "x" ] * 1000
    print "aesprng.shuffle (10/10)", \
          timeit((lambda c=c,L=L10: c.shuffle(L)), 1000)
    print "aesprng.shuffle (1000/1000)", \
          timeit((lambda c=c,L=L1000: c.shuffle(L)), 30)
    print "aesprng.shuffle (10/1000)", \
          timeit((lambda c=c,L=L1000: c.shuffle(L,10)), 1000)

    lkey = Keyset("keymaterial foo bar baz").getLionessKeys("T")
    print "lioness E (1K)", timeit((
        lambda lkey=lkey: lioness_encrypt(s1K, lkey)), 1000)
    print "lioness E (2K)", timeit((
        lambda lkey=lkey: lioness_encrypt(s1K, lkey)), 1000)
    print "lioness E (4K)", timeit((
        lambda lkey=lkey: lioness_encrypt(s4K, lkey)), 1000)
    print "lioness E (28K)", timeit((
        lambda lkey=lkey: lioness_encrypt(s28K, lkey)), 100)
    print "lioness E (32K)", timeit((
        lambda lkey=lkey: lioness_encrypt(s32K, lkey)), 100)
    print "lioness D (1K)", timeit((
        lambda lkey=lkey: lioness_decrypt(s1K, lkey)), 1000)
    print "lioness D (2K)", timeit((
        lambda lkey=lkey: lioness_decrypt(s1K, lkey)), 1000)
    print "lioness D (4K)", timeit((
        lambda lkey=lkey: lioness_decrypt(s4K, lkey)), 1000)
    print "lioness D (28K)", timeit((
        lambda lkey=lkey: lioness_decrypt(s28K, lkey)), 100)
    print "lioness D (32K)", timeit((
        lambda lkey=lkey: lioness_decrypt(s32K, lkey)), 100)

    bkey = Keyset("keymaterial foo bar baz").getBearKeys("T")
    print "bear E (1K)", timeit((
        lambda bkey=bkey: bear_encrypt(s1K, bkey)), 1000)
    print "bear E (2K)", timeit((
        lambda bkey=bkey: bear_encrypt(s1K, bkey)), 1000)
    print "bear E (4K)", timeit((
        lambda bkey=bkey: bear_encrypt(s4K, bkey)), 1000)
    print "bear E (28K)", timeit((
        lambda bkey=bkey: bear_encrypt(s28K, bkey)), 100)
    print "bear E (32K)", timeit((
        lambda bkey=bkey: bear_encrypt(s32K, bkey)), 100)
    print "bear D (1K)", timeit((
        lambda bkey=bkey: bear_decrypt(s1K, bkey)), 1000)
    print "bear D (2K)", timeit((
        lambda bkey=bkey: bear_decrypt(s1K, bkey)), 1000)
    print "bear D (4K)", timeit((
        lambda bkey=bkey: bear_decrypt(s4K, bkey)), 1000)
    print "bear D (28K)", timeit((
        lambda bkey=bkey: bear_decrypt(s28K, bkey)), 100)
    print "bear D (32K)", timeit((
        lambda bkey=bkey: bear_decrypt(s32K, bkey)), 100)