Example #1
0
def bleichenbacher(oracle: Oracle):
    """
    Bleichenbacher's attack

    Good ideas taken from:
        http://secgroup.dais.unive.it/wp-content/uploads/2012/11/Practical-Padding-Oracle-Attacks-on-RSA.html
    """

    k, n, e = oracle.get_k(), oracle.get_n(), oracle.get_e()

    B = pow(2, 8 * (k - 2))
    B2 = 2 * B
    B3 = B2 + B

    @typecheck
    def pkcs_conformant(c_param: int, s_param: int) -> bool:
        """
        Helper-Function to check for PKCS conformance.
        """
        pkcs_conformant.counter += 1
        return oracle.decrypt(i2osp(c_param * pow(s_param, e, n) % n, k))

    pkcs_conformant.counter = 0

    cipher = os2ip(oracle.eavesdrop())

    assert (pkcs_conformant(cipher, 1))

    c_0 = cipher
    set_m_old = {(B2, B3 - 1)}
    i = 1

    s_old = 0
    while True:
        if i == 1:
            s_new = ceildiv(n, B3)
            while not pkcs_conformant(c_0, s_new):
                s_new += 1

        elif i > 1 and len(set_m_old) >= 2:
            s_new = s_old + 1
            while not pkcs_conformant(c_0, s_new):
                s_new += 1

        elif len(set_m_old) == 1:
            a, b = next(iter(set_m_old))
            found = False
            r = ceildiv(2 * (b * s_old - B2), n)
            while not found:
                for s in interval(ceildiv(B2 + r * n, b),
                                  floordiv(B3 - 1 + r * n, a)):
                    if pkcs_conformant(c_0, s):
                        found = True
                        s_new = s
                        break
                r += 1

        set_m_new = set()
        for a, b in set_m_old:
            r_min = ceildiv(a * s_new - B3 + 1, n)
            r_max = floordiv(b * s_new - B2, n)
            for r in interval(r_min, r_max):
                new_lb = max(a, ceildiv(B2 + r * n, s_new))
                new_ub = min(b, floordiv(B3 - 1 + r * n, s_new))
                if new_lb <= new_ub:  # intersection must be non-empty
                    set_m_new |= {(new_lb, new_ub)}

        print("Calculated new intervals set_m_new = {} in Step 3".format(
            set_m_new))

        if len(set_m_new) == 1:
            a, b = next(iter(set_m_new))
            if a == b:
                print("Calculated:     ", i2osp(a, k))
                print("Calculated int: ", a)
                print("Success after {} calls to the oracle.".format(
                    pkcs_conformant.counter))
                return a

        i += 1
        s_old = s_new
        set_m_old = set_m_new
Example #2
0
def bleichenbacher(oracle: Oracle):
    """
    Bleichenbacher's attack

    Good ideas taken from:
        http://secgroup.dais.unive.it/wp-content/uploads/2012/11/Practical-Padding-Oracle-Attacks-on-RSA.html
    """

    k, n, e = oracle.get_k(), oracle.get_n(), oracle.get_e()

    B = pow(2, 8 * (k - 2))
    B2 = 2 * B
    B3 = B2 + B

    @typecheck
    def pkcs_conformant(c_param: int, s_param: int) -> bool:
        """
        Helper-Function to check for PKCS conformance.
        """
        pkcs_conformant.counter += 1
        return oracle.decrypt(i2osp(c_param * pow(s_param, e, n) % n, k))

    pkcs_conformant.counter = 0

    cipher = os2ip(oracle.eavesdrop())

    assert(pkcs_conformant(cipher, 1))

    c_0 = cipher
    set_m_old = {(B2, B3 - 1)}
    i = 1

    s_old = 0
    while True:
        if i == 1:
            s_new = ceildiv(n, B3)
            while not pkcs_conformant(c_0, s_new):
                s_new += 1

        elif i > 1 and len(set_m_old) >= 2:
            s_new = s_old + 1
            while not pkcs_conformant(c_0, s_new):
                s_new += 1

        elif len(set_m_old) == 1:
            a, b = next(iter(set_m_old))
            found = False
            r = ceildiv(2 * (b * s_old - B2), n)
            while not found:
                for s in interval(ceildiv(B2 + r*n, b), floordiv(B3 - 1 + r*n, a)):
                    if pkcs_conformant(c_0, s):
                        found = True
                        s_new = s
                        break
                r += 1

        set_m_new = set()
        for a, b in set_m_old:
            r_min = ceildiv(a * s_new - B3 + 1, n)
            r_max = floordiv(b * s_new - B2, n)
            for r in interval(r_min, r_max):
                new_lb = max(a, ceildiv(B2 + r*n, s_new))
                new_ub = min(b, floordiv(B3 - 1 + r*n, s_new))
                if new_lb <= new_ub:  # intersection must be non-empty
                    set_m_new |= {(new_lb, new_ub)}

        print("Calculated new intervals set_m_new = {} in Step 3".format(set_m_new))

        if len(set_m_new) == 1:
            a, b = next(iter(set_m_new))
            if a == b:
                print("Calculated:     ", i2osp(a, k))
                print("Calculated int: ", a)
                print("Success after {} calls to the oracle.".format(pkcs_conformant.counter))
                return a

        i += 1
        s_old = s_new
        set_m_old = set_m_new
Example #3
0
    """
    tests = [
        #{"k": 4, "p": 10007, "q": 10037},
        #{"k": 8, "p": 1000000007, "q": 1000000009},
        #{"k": 16, "p": 15309168720959725921, "q": 12819619822143804367},
        #{"k": 32, "p": 313115142601654954062569328755831304743, "q": 255336707253239299888475776540791782543},
        #{"k": 128, "p": 13244628888829977635820637741951867212791935321427723006722254687460420690588887758810928307766709750393036804634467753421052044765639091747501507784485213, "q": 11583722350869317111812024666321163171121150655325205224246499810906481321757898291274629991421369420603573230614994104724581115295807013606297300412089473},
        {
            "k":
            256,
            "p":
            167230636094866282461211664159158428279902699551992447152002026086321450931356694020366071860452874936312114743689156451204955885905421523426919810372766672329365549589557666294538091910136590569719360771818561583316969574158815755289605442067349031803550793473499645742177046498728201139371344588674279678939,
            "q":
            153746015991426629737627279764483089360526745536038013938043722107713599542535853191396561623967198520570205780805436781605500829408932188321165836162114053101365153759076284383142329005938490083741368370827739032497065588280706602245858167496933285469691492972704468586486254156236192774677901155398324342253
        }
    ]

    for test in tests:
        n = test["p"] * test["q"]
        B = pow(2, 8 * (test["k"] - 2))
        B2 = 2 * B
        m = b"ABCD"
        m = B2 + int(m, 16)
        bleichenbacher_simulation(test["k"], n, m)


if __name__ == "__main__":
    oracle = Oracle()
    #run_tests()
    bleichenbacher(oracle), oracle.get_k()
Example #4
0
        print("No luck for set_m_new = {} in Step 4".format(set_m_new))


@typecheck
def run_tests():
    """
    Tests to validate the algorithm.
    """
    tests = [
        #{"k": 4, "p": 10007, "q": 10037},
        #{"k": 8, "p": 1000000007, "q": 1000000009},
        #{"k": 16, "p": 15309168720959725921, "q": 12819619822143804367},
        #{"k": 32, "p": 313115142601654954062569328755831304743, "q": 255336707253239299888475776540791782543},
        #{"k": 128, "p": 13244628888829977635820637741951867212791935321427723006722254687460420690588887758810928307766709750393036804634467753421052044765639091747501507784485213, "q": 11583722350869317111812024666321163171121150655325205224246499810906481321757898291274629991421369420603573230614994104724581115295807013606297300412089473},
        {"k": 256, "p": 167230636094866282461211664159158428279902699551992447152002026086321450931356694020366071860452874936312114743689156451204955885905421523426919810372766672329365549589557666294538091910136590569719360771818561583316969574158815755289605442067349031803550793473499645742177046498728201139371344588674279678939, "q": 153746015991426629737627279764483089360526745536038013938043722107713599542535853191396561623967198520570205780805436781605500829408932188321165836162114053101365153759076284383142329005938490083741368370827739032497065588280706602245858167496933285469691492972704468586486254156236192774677901155398324342253}
    ]

    for test in tests:
        n = test["p"] * test["q"]
        B = pow(2, 8 * (test["k"] - 2))
        B2 = 2 * B
        m = b"ABCD"
        m = B2 + int(m, 16)
        bleichenbacher_simulation(test["k"], n, m)


if __name__ == "__main__":
    oracle = Oracle()
    #run_tests()
    bleichenbacher(oracle), oracle.get_k()