HiveBrain v1.2.0
Get Started
← Back to all entries
patternpythonMajor

4chan Tripcode Explorer in Python

Submitted by: @import:stackexchange-codereview··
0
Viewed 0 times
4chanexplorerpythontripcode

Problem

Background information for those of you who don't know what 4chan tripcodes are:

Via Wikipedia:


A tripcode is the hashed result of a password that allows one's identity to be recognized without storing any data about users. Entering a particular password will let one "sign" one's posts with the tripcode generated from that password.

Not displayed on Wikipedia:


With tripcodes, many people like to create special tripcodes for themselves, containing a certain string inside the text - for example the password "LC,T{af"

generating the tripcode "QeMbDfeels" which yields the phrase "feels", in relation to Wojak, also known as Feels Guy.

On my Intel Core 2 Duo T7400 @ 2.16GHz processor, I can get about 20000 tripcodes generated per second - I don't know if I can optimize this program any further, or my processor is just slow.

``
#!/usr/bin/python/
# -- coding: utf-8 -
from __future__ import division
import sys,re,string,crypt,random,time
Password,UpdateCount,ElapsedUpdates,Total,Matches,Rate,ElapsedCount,Filetext="0",0,0,0,0,0,0,"" #Saving myself a few lines by declaring all of these onto one line
Characters="!#$%&\"\'()*+,-./0123456789:;?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_
abcdefghijklmnopqrstuvwxyz{|}~" #Use all possible unicode characters accepted by 4chan
random.seed(time.time()) #Seed the random module with the current time
absolutestartTime=(time.time()) #Set an absolute start time for statistics
isCaseSensitive=Respond.query("Search for exact case / case-sensitive?") #Query for case-sensitive search
def GenerateTripcode(Password):
ShiftJIS=Password.encode('shift_jis', 'ignore')#Convert to SHIFT-JIS.
Tripcode=crypt.crypt( #Generate the tripcode
ShiftJIS, re.compile('[^\.-ElapsedUpdates]')\
.sub('.', (ShiftJIS+'...')[1:3])\
.translate(string.maketrans(':;?@[\\]^_`','ABCDEFGabcdef'))\
)[-10:]
return Tripcode
def GenerateRandomString(Length): return ''.join(random.c

Solution

I know this isn't what you're interested in, but I'm going to talk about style first - as is, I can't read this at all.

The biggest issue is that you seem to have some sort of dislike for whitespace - why?
Whitespace is your friend, and is the difference between legible and illegible code. If you really want some obfuscated code, then write it normally and then send it through an obfuscator. You need more newlines, spaces around operators, etc.

You could also follow the Python naming conventions better - variables and functions should be named with lower_snake_case.

I've also cleaned some things up in terms of variables (i.e. the characters are in the string module), the ternary expression, when you set the start_time (you want that to be as tight as possible), etc.

At this point, your code looks like this:

#!/usr/bin/python/ 
# -*- coding: utf-8 -*
from __future__ import division

import sys
import re
import string
import crypt
import random
import time

def generate_tripcode(password):
    shift_jis = password.encode("shift_jis", "ignore")
    tripcode = crypt.crypt(
        shift_jis, re.compile(r'[^\.-ElapsedUpdates]')\
            .sub('.', (shift_jis + '...')[1:3])\
            .translate(string.maketrans(':;?@[\\]^_`', 'ABCDEFGabcdef'))
        )[-10:]
    return tripcode

def generate_random_string(length):
    return ''.join(random.choice(characters) for _ in xrange(length))

def get_check(chk, tf):
    return chk if tf else string.lower(chk)

def display_statistics(matches, total, elapsed, rate, elapsed_seconds):
    print """
    Caught interrupt.
    {matches}    matches found
    {total}  codes generated in {elapsed}
    Average of ~{rate} tripcodes generated per second
    """.format(**locals())
        if matches > 0: 
            print "1 match found every ~{} seconds".format(round(elapsed_seconds / matches, 2))
            print "1 match found in every ~{} tripcodes".format(int(round(total / matches)))

try: 
    update_count = 0
    elapsed_updates = 0
    total = 0
    matches = 0
    rate = 0
    elapsed_count = 0
    filetext = ""
    characters = string.printable.split()[0] # get all non-whitespace, non-weird characters
    random.seed(time.time())    #Seed the random module with the current time

    is_case_sensitive = Respond.query("Search for exact case / case-sensitive?")

    find = sys.argv[1]

    if not is_case_sensitive:
        find = find.lower()

    absolute_start_time = time.time()
    start_time = time.time()
    while True:
        update_count += 1
        elapsed_count += 1
        total += 1
        password = generate_random_string(7)
        tripcode = generate_tripcode(password)

        if re.search(find, get_check(tripcode, is_case_sensitive)) > -1:
            output_string = "{}   >>>   {}\n".format(password, tripcode)
            filetext == output_string
            print "\033[K\r",   #Flush out any text from the current line
            print output_string
            mathces += 1

        if update_count == 100:
            update_count = 0
            elapsed_updates += 1
            status = "{} tripcodes    {}   tripcodes/sec\r".format(total, rate)
            print status

        if elapsed_updates == 10:
            elapsed_range = time.time() - start_time
            rate = int(round(elapsed_count / elapsed_range))
            elapsed_count = 0
            elapsed_updates = 0
            start_time = time.time()
except KeyboardInterrupt: 
    elapsed_seconds = time.time() - absolute_start_time
    elapsed = time.strftime("%M minutes, %S seconds", time.gmtime(elapsed_seconds))
    rate = int(round(total/elapsed_seconds))

    # Print statistics. 
    display_statistics(matches, total, elapsed, rate, elapsed_seconds)
    print "Writing matches to file...",

    with open("t.txt", "a") as file_:
        file_.write(filetext)
    print "done."


Now as for performance, the big choke is probably generate_tripcode - the most obvious way to make it faster is to move as many of the computations that don't change outside of the function.

Your regular expression has a minor bug - you indicated that you want to replace the characters .-z, however as written it will replace the range of characters from . to z - to fix this, make the - the last character in the regex.

regex = re.compile(r'[^\.z-]')
translator = string.maketrans(':;?@[\\]^_`', 'ABCDEFGabcdef')

def generate_tripcode(password):
    shift_jis = password.encode("shift_jis", "ignore")
    tripcode = crypt.crypt(
        shift_jis, regex.sub('.', (shift_jis + '...')[1:3]).translate(translator)
    )[-10:]
    return tripcode


Otherwise, if you can use a different cryptographic hash that is faster you'll probably see a much bigger performance increase, however that isn't an option for this situation. That is also part of why they use cryptographic hashes - to prevent you from doing this :)

In general though, if you want to push your computer to the limits, don

Code Snippets

#!/usr/bin/python/ 
# -*- coding: utf-8 -*
from __future__ import division

import sys
import re
import string
import crypt
import random
import time


def generate_tripcode(password):
    shift_jis = password.encode("shift_jis", "ignore")
    tripcode = crypt.crypt(
        shift_jis, re.compile(r'[^\.-ElapsedUpdates]')\
            .sub('.', (shift_jis + '...')[1:3])\
            .translate(string.maketrans(':;<=>?@[\\]^_`', 'ABCDEFGabcdef'))
        )[-10:]
    return tripcode


def generate_random_string(length):
    return ''.join(random.choice(characters) for _ in xrange(length))


def get_check(chk, tf):
    return chk if tf else string.lower(chk)


def display_statistics(matches, total, elapsed, rate, elapsed_seconds):
    print """
    Caught interrupt.
    {matches}    matches found
    {total}  codes generated in {elapsed}
    Average of ~{rate} tripcodes generated per second
    """.format(**locals())
        if matches > 0: 
            print "1 match found every ~{} seconds".format(round(elapsed_seconds / matches, 2))
            print "1 match found in every ~{} tripcodes".format(int(round(total / matches)))


try: 
    update_count = 0
    elapsed_updates = 0
    total = 0
    matches = 0
    rate = 0
    elapsed_count = 0
    filetext = ""
    characters = string.printable.split()[0] # get all non-whitespace, non-weird characters
    random.seed(time.time())    #Seed the random module with the current time

    is_case_sensitive = Respond.query("Search for exact case / case-sensitive?")


    find = sys.argv[1]

    if not is_case_sensitive:
        find = find.lower()

    absolute_start_time = time.time()
    start_time = time.time()
    while True:
        update_count += 1
        elapsed_count += 1
        total += 1
        password = generate_random_string(7)
        tripcode = generate_tripcode(password)

        if re.search(find, get_check(tripcode, is_case_sensitive)) > -1:
            output_string = "{}   >>>   {}\n".format(password, tripcode)
            filetext == output_string
            print "\033[K\r",   #Flush out any text from the current line
            print output_string
            mathces += 1

        if update_count == 100:
            update_count = 0
            elapsed_updates += 1
            status = "{} tripcodes    {}   tripcodes/sec\r".format(total, rate)
            print status

        if elapsed_updates == 10:
            elapsed_range = time.time() - start_time
            rate = int(round(elapsed_count / elapsed_range))
            elapsed_count = 0
            elapsed_updates = 0
            start_time = time.time()
except KeyboardInterrupt: 
    elapsed_seconds = time.time() - absolute_start_time
    elapsed = time.strftime("%M minutes, %S seconds", time.gmtime(elapsed_seconds))
    rate = int(round(total/elapsed_seconds))

    # Print statistics. 
    display_statistics(matches, total, elapsed, rate, elapsed_seconds)
    print "Writing matches to file...",

    with open("t.txt", "a
regex = re.compile(r'[^\.z-]')
translator = string.maketrans(':;<=>?@[\\]^_`', 'ABCDEFGabcdef')

def generate_tripcode(password):
    shift_jis = password.encode("shift_jis", "ignore")
    tripcode = crypt.crypt(
        shift_jis, regex.sub('.', (shift_jis + '...')[1:3]).translate(translator)
    )[-10:]
    return tripcode
regex = re.compile(r'[^\.ElapsedUpdates-]')
translator = string.maketrans(':;<=>?@[\\]^_`', 'ABCDEFGabcdef')

def generate_tripcode(password):
    shift_jis = (password.encode("shift_jis", "ignore") + '...')[1:3]
    tripcode = crypt.crypt(
        shift_jis, regex.sub('.', shift_jis).translate(translator)
    )[-10:]
    return tripcode

Context

StackExchange Code Review Q#120204, answer score: 21

Revisions (0)

No revisions yet.