Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- # Get as many imports on the same line as possible without going over 80 char
- # I'm not sure if it's better practice but it looks nicer to me than a
- # vertical pile of import statements :)
- import time, praw, os, smtplib, email, datetime, html, configparser
- #import premailer,
- #import mysql.connector
- from passlib.hash import pbkdf2_sha256, sha256_crypt
- from email import encoders
- from email.header import Header
- from email.mime.text import MIMEText
- from email.mime.multipart import MIMEMultipart
- # This class can be pulled out into its own file, something like
- # "configuration.py". Then you can access it using
- # from configuration import Configuration
- # and use it just like you were including it directly.
- class Configuration:
- """ Retrieves config information from a text file and stores it in
- a dict. Currently defaults to config.ini if no text file is
- specified. """
- # DEFAULTS
- DFILE = "config.ini"
- DSECTION = "mysql"
- # METHODS
- # Create a new Configuration
- def __init__(self, configfile=None, section=None):
- self.configfile = configfile if configfile != None else Configuration.DFILE
- sect = section if section != None else Configuration.DSECTION
- config = configparser.ConfigParser()
- config.read(self.configfile)
- self.usr = config.get(sect,'user')
- self.passwd = config.get(sect,'password')
- self.hst = config.get(sect,'host')
- self.db = config.get(sect,'database')
- @property
- def user(self):
- return self.usr
- @property
- def password(self):
- return self.passwd
- @property
- def host(self):
- return self.hst
- @property
- def database(self):
- return self.db
- # Useful for passing to MySQL
- @property
- def full(self):
- return {"user" : self.user,
- "password" : self.password,
- "host" : self.host,
- "database" : self.database}
- # This class can be pulled out into its own file, something like
- # "passwords.py". Then you can access it using
- # from passwords import Password
- # and use it just like you were including it directly.
- class Password:
- """Handles password salting and hashing.
- Use hashpw() to create a hashed password.
- Use checkpw() to see if a user's submitted password matches the
- password on file.
- """
- # DEFAULTS
- DROUNDS = 200000
- DSALTSIZE = 16
- DCHANCES = 5
- def __init__(self, rounds=None, saltsize=None, chances=None):
- self.rounds = rounds if rounds != None else Password.DROUNDS
- self.saltsize = saltsize if saltsize != None else Password.DSALTSIZE
- self.chances = chances if chances != None else Password.DCHANCES
- self.storedpws = []
- def hashpw(self, password):
- hashedpw = sha256_crypt.encrypt(password, rounds=self.rounds, salt_size = self.saltsize)
- self.storedpws.append(hashedpw)
- return hashedpw
- def checkpw(self, hpw):
- verified, i = False, 0
- # give them a certain number of chances to get it right (default: 5)
- while verified != True and i < self.chances:
- i += 1
- ipw = input("Password: ")
- if type(hpw) == list:
- for pw in hpw:
- if sha256_crypt.verify(ipw, pw):
- verified = True
- break
- else:
- if sha256_crypt.verify(ipw,hpw):
- verified = True
- return verified
- def checkpwlocal(self):
- return self.checkpw(self.storedpws)
- def checkpwremote(self, username=None, connection=None):
- if username == None or type(username) != str:
- raise ValueError("You must submit a username as a string.")
- if connection == None or type(connection) != Connection:
- raise ValueError("You must submit a connection as a Connection object.")
- output = connection.selectone("programPassword","prawuse",
- ["programLoginName = '{}'".format(username), "LIMIT 1"])
- # hashedpw = output[0].encode("utf-8")
- return self.checkpw(output[0].encode("utf-8"))
- # This class can be pulled out into its own file, something like
- # "connection.py". Then you can access it using
- # from connection import Connection
- # and use it just like you were including it directly.
- #class Connection:
- """Creates a connection to the MySQL server.
- We can select results to be iterated over later, we can select
- a single row, or we can select all the rows.
- Insert and Update methods can be built later.
- """
- """ #DEFAULTS
- # Initialize with a dict of values: user, password, host, database
- def __init__(self, config):
- self.conn = mysql.connector.connect(**config)
- self.cursor = self.conn.cursor()
- # Returns all results as a result object
- def select(self, columns, table, conditions=None):
- qstr = "SELECT {0} FROM {1}".format(columns, table)
- if conditions != None:
- qstr += " WHERE"
- for condition in conditions:
- qstr += " {}".format(condition)
- return self.cursor.execute(qstr)
- # Returns ONLY THE FIRST RESULT as a tuple of objects
- def selectone(self, columns, table, conditions=None):
- results = self.select(columns, table, conditions)
- wanted = results.fetchone()
- while results != None: #we have to get all the data out of this
- results.fetchone() #request before we can send another on
- return wanted #the same connection
- # Returns all results as a list of tuples of objects
- def selectall(self, columns, table, conditions=None):
- results = self.fetch(columns, table, conditions)
- return results.fetchall()
- #we don't need any update methods yet so I won't write them yet"""
- def main():
- #Let's do some setup
- config = Configuration('config.ini')
- print(config.full)
- #conn = Connection(config.full)
- pw = Password()
- hashedpw = pw.hashpw(input("What's the password? ").strip())
- print("Now let's check it.")
- if pw.checkpwlocal() == True:
- print("You got it!")
- else:
- print("Nope. :(")
- if __name__ == "__main__":
- main()
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement