示例#1
0
def decryptWithSubstitution(ciph):
    """Decrypt a general polyalphabetic substitution cipher using mulitple simultaneous hill-climbing algorithms."""

    ciph = Format.keepOnly(ciph.lower(), ALPH)
    length = len(ciph)

    subs = []
    for x in range(0, 7):
        substring = ciph[x::7]
        key = [y[0] for y in FreqAnalysis.getFrequencies(substring).most_common() if y[0] in ALPH]
        for char in letterProbs:
            if char not in key:
                key.append(char)
        subs.append((substring, key))

    i = 0
    bestScore = 0
    result = []
    for sub in subs:
        keyMap = dict(zip(sub[1], letterProbs))
        result.append(Substitution.sub(sub[0], keyMap))
    result = "".join("".join(b) for b in zip_longest(*result, fillvalue=""))
    bestScore = DetectEnglish.detect(result, length=length)

    while i < 10000:
        x = random.randint(0, len(subs) - 1)
        y = random.randint(1, len(subs[x][1]) - 1)
        z = random.randint(1, len(subs[x][1]) - 1)
        subs[x][1][y], subs[x][1][z] = subs[x][1][z], subs[x][1][y]
        result = []
        for sub in subs:
            keyMap = dict(zip(sub[1], letterProbs))
            result.append(Substitution.sub(sub[0], keyMap))
        result = "".join("".join(b) for b in zip_longest(*result, fillvalue=""))
        score = DetectEnglish.detect(result, length=length)
        if score > bestScore:
            bestScore = score
            i = 0
        else:
            subs[x][1][y], subs[x][1][z] = subs[x][1][z], subs[x][1][y]
        i += 1

    result = []
    for sub in subs:
        keyMap = dict(zip(sub[1], letterProbs))
        key = ""
        for x in ALPH:
            for k, v in keyMap.items():
                if k == x:
                    key += v
        result.append(Substitution.sub(sub[0], keyMap))
    result = "".join("".join(b) for b in zip_longest(*result, fillvalue=""))

    return result
示例#2
0
def getBest(possKeys, ciph):
    """Find best mapping in given possibilities."""

    results = []
    for key in possKeys:
        keyMap = dict(zip(ALPH, key))
        result = sub(ciph, keyMap)
        results.append((key, DetectEnglish.detect(result),
                        -DetectEnglish.chiSquared(result)))

    best = max(results)
    bestMap = dict(zip(ALPH, best[0]))
    result = sub(ciph, bestMap)

    return result, best[1], bestMap
示例#3
0
def reverseText():
    args = {"title": "Reverse Text", "ciphText": "", "result": "", "score": 0}
    if request.method == "POST":
        args["ciphText"] = ciph = request.form["ciphInput"]
        args["result"] = plain = ciph[::-1]
        args["score"] = DetectEnglish.detectWord(SpaceAdd.addLongest(plain)) * 100
    return render_template(f"tools/reversetext.html", **args)
示例#4
0
def freqAnalysis():
    args = {"title": "Frequency Analysis", "ciphText": "", "score": 0}
    if request.method == "POST":
        args["ciphText"] = ciph = request.form["ciphInput"]
        args["score"] = DetectEnglish.detectWord(SpaceAdd.addLongest(ciph)) * 100
    plotFreq(args["ciphText"])
    return render_template(f"tools/freqanalysis.html", **args)
示例#5
0
def decrypt(ciph):
    """Use a hill-climbing algorithm to decipher a substituted alphabet."""

    ciph = Format.keepOnly(ciph.lower(), ALPH)
    if not ciph:
        return ciph, {x: "" for x in ALPH}

    key = [
        x[0] for x in FreqAnalysis.getFrequencies(ciph).most_common()
        if x[0] in ALPH
    ]
    keyMap = dict(zip(key, letterProbs))

    bestKey = []
    bestScore = 0
    i = 0
    while i < 1000:
        result = sub(ciph, keyMap)
        score = DetectEnglish.detect(result)
        if score > bestScore:
            bestScore = score
            bestKey = list(key)
            i = 0
        x = random.randint(1, len(key) - 1)
        y = random.randint(1, len(key) - 1)
        key = list(bestKey)
        key[x], key[y] = bestKey[y], bestKey[x]

        keyMap = dict(zip(key, letterProbs))
        i += 1
    bestMap = dict(zip(key, letterProbs))
    result = sub(ciph, bestMap)
    return result, bestMap
示例#6
0
def _decryptLongKey(text, keylen):
    """Decrypt long keys (length >= 9) using a hill-climbing algorithm."""

    key = list(range(keylen))
    random.shuffle(key)

    bestKey = []
    bestScore = 0
    i = 0
    while i < 10000:
        if random.uniform(0, 10) < 1:
            random.shuffle(key)
        result = recreate(shuffle(text, key))
        score = DetectEnglish.detect(result)
        if score > bestScore:
            bestScore = score
            bestKey = list(key)
            i = 0
        x = random.randint(0, len(key) - 1)
        y = random.randint(0, len(key) - 1)
        key = list(bestKey)
        key[x], key[y] = bestKey[y], bestKey[x]

        i += 1
    result = recreate(shuffle(text, bestKey))

    return result, list(map(str, key))
示例#7
0
def addSpaces():
    if request.method == "POST":
        plainText = Format.remove(request.json["plain"], SPACE)
        plainText = SpaceAdd.addLongest(plainText)
        score = DetectEnglish.detectWord(plainText) * 100
        return json.dumps({"plain": plainText, "score": f"{score}% certainty"})
    return "error"
示例#8
0
def addForwards(text):
    """Insert spacing into text."""

    with open("static/txt/wordlist.txt", encoding="utf-8") as f:
        wordset = set(f.read().split("\n"))

    string = Format.keepOnly(text, ALPH)

    result = []
    maxLen = DetectEnglish.getLongest()

    x = maxLen
    while True:
        word = string[:x]
        if word in wordset:
            result.append(word)
            string = string[x::]
            x = maxLen
        else:
            x -= 1

        if x == 0 and string:
            result.append(string[0])
            string = string[1::]
            x = maxLen
        elif not string:
            break

    return " ".join(result)
示例#9
0
def decrypt(ciph, keylen=0, key=""):
    """
    Attempt decryption of the transposition-enciphered text.

    One of keylen or key is required to function.
    """

    if not (key or keylen):
        return "", ""

    ciph = Format.keepOnly(ciph.lower(), ALPH, NUMS)
    text = _process(ciph, keylen=keylen, key=key)

    if key:
        return _decryptWithKey(text, key.split(","))
    if keylen < 9:
        bestResult, bestKey = _decryptShortKey(text)
    else:
        bestResult, bestKey = _decryptLongKey(text, keylen)

    bestScore = DetectEnglish.detectWord(SpaceAdd.addLongest(bestResult))

    text = _process(ciph, keylen=len(ciph) // keylen, key=key)
    text = "".join(text)
    text = _process(text, keylen=keylen, key=key)
    if keylen < 9:
        result, key = _decryptShortKey(text)
    else:
        result, key = _decryptLongKey(text, keylen)
    score = DetectEnglish.detectWord(SpaceAdd.addLongest(result))
    if score > bestScore:
        bestResult = result
        bestKey = key

    overflow = len(ciph) % keylen
    if overflow != 0:
        bestScore = 0
        lastset = bestResult[-overflow:]
        overflow = len(lastset)
        for perm in itertools.permutations(lastset, overflow):
            result = bestResult[:-overflow] + "".join(perm)
            score = DetectEnglish.detectWord(SpaceAdd.addLongest(result))
            if score > bestScore:
                bestScore = score
                bestResult = result

    return bestResult, bestKey, bestScore
示例#10
0
def caesar():
    args = {"title": "Caesar", "ciphText": "", "result": "", "score": 0}
    if request.method == "POST":
        from Ciphers import Caesar

        ciphText = request.form["ciphInput"].lower()
        result, _ = Caesar.decrypt(ciphText)
        score = DetectEnglish.detectWord(SpaceAdd.addLongest(result)) * 100

        args = {"title": "Caesar", "ciphText": ciphText, "result": result, "score": score}
    return render_template(f"ciphers/caesar.html", **args)
示例#11
0
def _decryptShortKey(text):
    """Decrypt ciphertext if the key is short (length < 9) using a brute-force attack."""

    bestKey = []
    bestScore = 0
    for key in itertools.permutations(range(len(text))):
        result = recreate(shuffle(text, key))
        score = DetectEnglish.detect(result)
        if score > bestScore:
            bestScore = score
            bestKey = list(key)
    result = recreate(shuffle(text, bestKey))

    return result, list(map(str, bestKey))
示例#12
0
def substitution():
    args = {"title": "Substitution", "ciphText": "", "result": "", "score": 0, "vals": {}}
    if request.method == "POST":
        from Ciphers import Substitution

        ciphText = Format.remove(request.form["ciphInput"], PUNC).lower()

        if request.form.get("useSpace"):
            result, vals = Substitution.decryptWithSpaces(ciphText)
        else:
            result, vals = Substitution.decrypt(ciphText)
        score = DetectEnglish.detectWord(SpaceAdd.addLongest(result)) * 100

        args = {"title": "Substitution", "ciphText": ciphText, "result": result, "score": score, "vals": vals}
    return render_template(f"ciphers/substitution.html", **args)
示例#13
0
def transposition():
    args = {"title": "Transposition", "ciphText": "", "result": "", "score": 0, "keylen": "", "key": ""}
    if request.method == "POST":
        from Ciphers import Transposition

        ciphText = Format.remove(request.form["ciphInput"], PUNC).lower()
        keylen = int(request.form["keylenInput"] or 0)
        key = request.form["keyInput"]

        result, key = Transposition.decrypt(ciphText, key=key, keylen=keylen)
        key = ",".join(key)
        score = DetectEnglish.detectWord(SpaceAdd.addLongest(result)) * 100

        args = {"title": "Transposition", "ciphText": ciphText, "result": result, "score": score, "keylen": keylen, "key": key}
    return render_template(f"ciphers/transposition.html", **args)
示例#14
0
def decrypt(ciph):
    """Try every possible shift and choose the best result."""

    bestScore = 9e99
    bestKey = ""
    bestResult = ""
    for i in range(26):
        result = shift(ciph, i)
        score = DetectEnglish.chiSquared(result)
        if score < bestScore:
            bestScore = score
            bestResult = result
            bestKey = ALPH[i]

    return bestResult, bestKey
示例#15
0
def decryptWithKeylen(ciph, keylen):
    """Decrypt each 'column' of ciphertext as separate Caesar ciphers."""

    sub = []
    for i in range(keylen):
        sub.append(ciph[i::keylen])

    results = []
    key = []
    for x in sub:
        result, shift = Caesar.decrypt(x)
        results.append(result)
        key.append(shift)
    result = Transposition.recreate(results)
    score = DetectEnglish.detect(result)

    return result, ",".join(key), score
示例#16
0
def vigenere():
    args = {"title": "Vigenere", "ciphText": "", "result": "", "score": 0, "keylen": "", "key": ""}
    if request.method == "POST":
        from Ciphers import Vigenere

        ciphText = request.form["ciphInput"]
        keylen = request.form["keylenInput"]
        key = request.form["keyInput"]

        if request.form.get("oddAlph"):
            result = Vigenere.decryptWithSubstitution(ciphText)
        else:
            result, key, _ = Vigenere.decrypt(ciphText, key=key, keylen=keylen)
        score = DetectEnglish.detectWord(SpaceAdd.addLongest(result)) * 100

        args = {"title": "Vigenere", "ciphText": ciphText, "result": result, "score": score, "keylen": keylen, "key": key}
    return render_template(f"ciphers/vigenere.html", **args)
示例#17
0
def decryptWithKey(ciph, key):
    """Use given key to decrypt text."""

    key = key.split(",")
    keylen = len(key)

    sub = []
    for i in range(keylen):
        sub.append(ciph[i::keylen])

    results = []
    for i, x in enumerate(sub):
        result = Caesar.shift(x, key[i])
        results.append(result)
    result = Transposition.recreate(results)
    score = DetectEnglish.detect(result)

    return result, ",".join(key), score
示例#18
0
def subInputs():
    if request.method == "POST":
        changed = request.json["name"][0]
        newval = request.json["val"].lower()
        if newval == "":
            newval = "_"
        ciphText = Format.keepOnly(request.json["ciph"].lower(), ALPH)
        plainText = Format.remove(request.json["plain"], SPACE).lower()
        if plainText == "":
            new = ''.join([newval if x in changed else "_" for x in ciphText])
        else:
            plainText = [x for x in plainText]
            for i, letter in enumerate(ciphText):
                if letter == changed:
                    plainText[i] = newval
            new = "".join(plainText)
        score = DetectEnglish.detectWord(SpaceAdd.add(new)) * 100
        return json.dumps({"plain": new, "score": f"{score}% certainty"})
    return "error"
示例#19
0
def addLongest(text):
    """Insert spacing into text. Longest identified words inserted first."""

    with open("static/txt/wordlist.txt", encoding="utf-8") as f:
        wordset = set(f.read().split("\n"))

    string = Format.keepOnly(text, ALPH)

    result = [""] * len(string)
    maxLen = DetectEnglish.getLongest()

    for chunkSize in range(maxLen, 0, -1):
        for i in range(0, len(string) - chunkSize + 1):
            if string[i:i + chunkSize] in wordset:
                result[i] = string[i:i + chunkSize]
                string = string.replace(string[i:i + chunkSize],
                                        "." * chunkSize)

    result = filter(lambda x: x != "", result)

    return " ".join(result)
示例#20
0
def decrypt(ciph, key="", keylen=0):
    """Automatically decrypt a vigenere cipher using the Index of Coincidence to find possible key lengths."""

    ciph = Format.keepOnly(ciph.lower(), ALPH)

    if key:
        return decryptWithKey(ciph, key)
    if keylen:
        return decryptWithKeylen(ciph, int(keylen))

    sub = {}
    for i in range(2, 26):
        sub[i] = []
        for j in range(i):
            sub[i].append(ciph[j::i])

    ic = {}
    for i in sub:
        avgic = sum(map(DetectEnglish.indexOfCoincidence, sub[i])) / i
        if avgic > 0.06:
            ic[i] = avgic

    bestKey = ""
    bestScore = 0
    bestResult = ""
    for i in ic:
        results = []
        key = []
        for x in sub[i]:
            result, shift = Caesar.decrypt(x)
            results.append(result)
            key.append(shift)
        result = Transposition.recreate(results)
        score = DetectEnglish.detect(result)
        if score > bestScore:
            bestScore = score
            bestKey = "".join(key)
            bestResult = result

    return bestResult, ",".join(bestKey), bestScore