使用SHA1算法验证Hash值,校验数据库后,判断密码及其他字段是否被修改。
Background
For this project we are shifting our attention to pointers, structs and arrays
of structs. The main focus of this project is to react to the storage demands
of our program and “grow” our arrays when they are full.
Context
Sit down and let me tell you a story; a story about a bank with terrible
security. Every night Bank XYZ gets hacked. Every night an unknown attacker
gains access to the main account file on the bank’s computer. The attacker has
the ability to modify the record in any way they wish. Luckily for us, this
attacker attended a school other than VT and they are not aware of the signed
hash code at the end of the record and they make no effort to hide their
tracks. Mainly they are after the vast store of gold in each of the account
holder’s accounts.
So your job as the bank’s main super hero, also known as the system admin, is
to check each day for hacked records. When this occurs you then generate a
report of which accounts were hacked, update their password, thus saving the
account holders, and the bank, many thousands of lost pounds of gold. You also
have the ability to add new accounts, remove old accounts, and of course save
an updated account file.
Details
The program you run each day responds to a series of commands. The commands
may have options you can specify. The options depend on the command. The
commands will be listed below. Each command has output. Some of the commands
many not be successful and there are messages that correspond to those as
well.
Commands
load filename
This is the main way data is entered into our system. The load command is
followed by a filename. The filename is a csv file of records. The records
will be described below. The output from the load command is the filename that
was loaded and how many records were loaded.
locked
This command takes no options. It’s job is to go through the list and see
which records were hacked. If any records were hacked, then a list of those
records is produced. If no records are hacked, then an output message
indicating that is given.
unlock id new password
This command will attempt to unlock the given account by it’s id. If the id is
found, the password is checked to see if it meets our high standards. If the
password is up to our security standards, the records is unlocked, the
password is updated, and the signed hash is recomputed using the new data.
There are two error conditions that can occur. 1. The account id is not found.
In this case, a simple message about not finding that account is given. 2. The
account is found, but the password is not secure enough. In this case, the
account remains locked, the password is not updated, and there is a message
about not unlocking the account.
add new record information
This record format matches the ones in the file, except it does not have a
signed hash code at the end. The record is parsed and if the password is up to
our security standards, then the account is added to our array at the end. If
the password does not meet our standards, then the account is not added.
remove id
This will attempt to remove the record from the array. If the id is found, we
will slide down the “higher” accounts down an index position to “cover up”
this record. If the id is not found nothing is done. If the record is removed,
a message indicating that is given, and if not, a message indicating that the
id was not found is issued.
save filename
This will save the array into the given file name. The format needs to match
the load file format in this way, you could reload a saved file. Any new or
removed records will appear or not in the saved file. The output of this is
the file you are using for saving and the number of records saved into the
file.
Data
The data in this project is CSV data. It will consist of “records” in the
following format:
name,id,account,username,password,signedhash
The name is a string. It will contain spaces. The id is just that, an
identifier for the record. Each record will have a unique id and it can be
used for searching for the record on an update or removal. The account is a
made up bunch of numbers attempting to represent a bank account number. It is
purely fictional. Do not go to Bank XYZ and attempt to access any of these
accounts. The username is also made up. I’ve just jammed together the person’s
name.
The password is also made up. It has to adhere to the set of rules below. The
signed hash is more interesting and will be described in more detail below. In
a nutshell, it’s a bunch of letters that have been bit manipulated to produce
an int.
Password Rules
The rules for the password are fairly straightfoward, they are as follows:
- The password must be at least 10 characters.
- The password must contain at least one of each of the following types of characters, upper case letter, lower case letter, a number and a punctuation character.
To determine the characters I suggest looking at the cctype (Links to an
external site.) library over at cplusplus.com (Links to an external site.) and
in particular look at the isupper, islower, ispunct and isdigit functions.
Hashing
Okay so in our records at the end there’s this strange number and I keep
talking about this hashing then signing it. This is a basic attempt at some
security. We are going to be using a hashing algorithm known as SHA1. The
basic idea of SHA is to take a message and produce a hash or a condensed
version of the message. Then we will “sign” the message using a sign function.
The function will essentially take the message and a key and produce an
integer value. This integer will vary per record and gives a primitive way to
see if a record was tampered with.
Here’s how I call them in my code:
string message;
message = r.name+r.id+r.account+r.username+r.password;
SHA1 checksum;
checksum.update(message);
r.hash = checksum.final();
r.verifiedHash = sign2( r.hash, r.id );
—|—
So the code above is from my code and my struct is called Record and r is a
variable of my Record struct. My struct contains the fields that are shown in
the above code (and some that aren’t shown). verifiedHash is an unsigned int
and the rest of what is shown are all strings.
So you can see from the code here, I store the hash and the signedHash in my
record. You do not need to do that but you are welcome to do so. Also in this
function, r is a variable of type Record, where Record is the name of my
struct.
Okay, yes, the header file is named SHA1.hpp. This is okay. hpp is just a
header for C++. Move the files into your directory with your project. Add them
to your project and all should be fine. You will not need to add sha1.hpp to
your zip when you submit. You will need to add the sha1.cpp to your zip.
This main.cpp is a simple piece of code that should run in your Visual Studio.
It shows how to create a SHA1 object and how to call the methods to update and
finalize the hash and also how to call the sign2 function. It shows the data
types of each of the parameters and return types.
Requirements
- You must declare a function with the signature
void bankAdmin(string commands, string output );
in a file named bank.h - You must create a struct to store the information in the file. You may add fields that are not stored, e.g. a field to indicate locked, a field to store the hash and the signed hash, etc.
- You must use a dynamically allocated array of structs to store the data. (*) See below for details about if you choose not to do this.
* If you can’t get the dynamic array working, you may use a static array, but you won’t get a grade higher than an 80. - You may not use classes for this.
- You may not use Vector, List, or any of the other STL storage containers.
- No global variables!
- You must implement a function for each of the commands.
- No global variables! (Yes twice)
- You must follow the Code Style Guidelines on Canvas.
- You array must start at size of 10 and double when it is full.
- Hmm…more?
Grading
Zip up your bank.h and bank.cpp and any other files you wrote. and turn them
in to Web-CAT before you go home to eat turkey, or just sleep all week. Don’t
forget to use the include guards around your struct and also you will need to
add the sha1.cpp to your zip.