A Simple Partitioning Tip

Deciding how to partition a hard drive is not necessarily a simple task. Depending on what you want to do with it, your partitioning scheme may vary greatly. For those with specific needs I put forward a practical tip: Make all your operating system partitions the exact same size. I've learned the value of this several times over in situations that called for experimentation/backup with/for an operating system.

I will use the *nix tools fdisk (the Windows version of fdisk will not suffice) and dd, and consequentially assume that the reader has minimal *nix experience and access to some form of a *nix like system. Linux live CDs are adequate, as will (I believe) OSX. The *nix system will be used to perform the delicate initial partitioning and the partition clones thereafter.

I always dual-boot Windows and Linux, keep a third partition around for experimenting with other operating systems, and have a fourth partition blank. All four of these partitions are the exact same size, which offers me flexibility in moving them around. The biggest advantage is that it allows me to perform a byte-for-byte clone any one partition onto a second partition, perform whatever perverse thing I'm experimenting with on the first partition, and then restore it if something goes wrong. Or I can just boot straight to the new copy of the partition I cloned. Somewhat time consuming, but simple and error-proof.

I know this concept may strike some as a waste of time and space, but it's not inefficient as it may sound. Cloning a 20GB partition can be done over lunch and, like many others, I have a hard disk exclusively devoted to operating systems, no one of which needs more than 25GB.

There are several reasons why you might want to backup an entire partition. The need to do so for a *nix system is less pronounced, because the flexibility of *nix systems lets you do a file-level copy between partitions without adverse effects. But doing a byte-for-byte direct copy isn't much longer than a file-based copy, and removes any of the file-based copy complications. As well, Windows systems are attached to their partitions and if they are copied on the file level to a new file system they will not work, so doing a byte-by-byte image of a Windows system is almost a must for backup purposes.

The problem, though, is that if you rely on a partition manager like the default Windows manager or GParted (which is the default partition manager in the Ubuntu installation process) to create your partitions for you, as odd as it may seem, you aren't guaranteed to get partitions the exact size you specified. I don't know the details, but creating two 20GB partitions does not guarantee you of getting two partitions of the same size. Thus when you go back to try and clone one partition to another you may discover that the destination partition is, say, 8MB smaller than the source partition, and there will be hell to pay.

Creating Precisely-Sized Partitions

  • Open the disk to partition with fisk:

    # fdisk /dev/sda

    Use the "p" command to get a printout of my current table. If the disk is new, the printout should be empty.

  • Determine how large you wish the partitions to be. Create a new partition and choose the starting first sector (use the default if you are creating them sequentially). Then select the last sector by using the +XG to indicate that the last sector should be X gigabytes worth of sectors after the first. This should work with both primary and extended partitions, with one exception noted below.
  • Exception: There is a special partition that requires a non-default starting sector. The first partition within an extended partition will start in the same cylinder as the extended partition marker, and thus share some space with said marker and not be the exact size specified. To correct this, create the first "inner" extended partition one sector after the beginning of the "outer" extended partition. This will result in a few bytes of wasted space, but if both partitions start on the same sector then size of the final partition will be slightly too small.

Copying Partitions

  • Decide which partition will be the source and which will be the destination. Use dd to copy from the source to the destination:
    # dd if=/dev/sda2 of=/dev/sda4 bs=8M

    A key parameter here is the "bs" option, which tells dd how many bytes to read and write each time. Read/write operations to disks are relatively slow and have significant overhead so you want to make each read/write operation worth your computer's time. I've found 8MB to be about the most efficient block size to use for each read and write. If you fail to specify a value then the default of 512 bytes will be used, this can make the process take on the order of 100 times longer to finish.

Obviously, copying partitions also applies to copying entire disks if the disks are the exact same size. This can be used make manual backups of entire drives.

My Review of ABeka Acadamy

ABeka Academy is the child of the larger Pensacola Christian College that handles grade school and high school. The two academic institutions have the same philosophies, same teachings, same standards, and are, ultimately, run by the same people. ABeka is based out of Pensacola, Florida, and they offer a nation-wide home school charter program for home school families who want to give their kids an at home, Christian education. They offer their program for the entire K-12 grade spectrum.

At a glance ABeka may seem like the perfect answer to a lot of home schoolers' needs. They provide the books, materials, instruction, grades, and a diploma. All you have to do is send them a few thousand dollars per year and grade the student's quizzes with an answer key ABeka provides.

But for all ABeka does, there's a lot they don't do. I'm an ABeka high school student, and everything I say comes from three years of experience in ABeka's high school program, and I say that ABeka is not all they're made out to be. (Note that I only spent three years in ABeka -- I'll explain later.)

Like a lot of students, I joined the ABeka high school program my freshman year because I needed the instruction their DVD courses offer. My mom's teaching was adequate until then, but she had three younger kids to take care of and home school as well and the material I was covering in school was getting harder for her to explain. So when I started high school, we decided it would be easier for both of us if I did all my schooling via ABeka. We did the same research that basically all other prospective ABeka students have done, and they appeared to be a solution for our needs. As it turned out, we didn't know as much about them as perhaps we should have.

I took classes at a community college during high school. Not being the type of person who wanted to take two classes when one would suffice, I asked ABeka if they would give me credit for my college classes and count them towards my high school record. This seemed like a reasonable request, since every public and private school I know of does so, on the grounds that a college class should meet the standards for a high school class.

But no. My college classes may have been good enough for UC Davis and UC Berkeley (the two schools that accepted me when I transfered out of community college years later), but they were not good enough for ABeka. ABeka said that they would not give me credit for college classes, and, when pressed for the reason why, said that it was because they could not validate that the classes I took would satisfy their standards. That is, seriously, what we were told. My college classes weren't veritably good enough for their high school requirements.

Now, I could understand why ABeka might frown on an anthropology class, biology class, or any class in that general area because of the philosophical and (potentially) anti-Christian teachings commonly associated with such classes (ABeka is, after all, a Christian school) but I was asking ABeka to accept computer and math classes -- classes that carry no such philosophical baggage. In fact, they were classes that ABeka didn't even offer but that I would need for my college major later in life. (Ironically, ABeka is big on "preparing you for college", by the way.) It is standard procedure for kids in high school to take a community college class when their high school doesn't offer an equivalent class –- I've shared classes with a couple of them myself - but ABeka apparently doesn't see fit to accommodate anyone in this area, and their refusal to credit students for college classes boxes some students into a very tight corner, as I'll explain later.

Along the lines of ABeka's high standards, they're very anal about problem solving methods. I happen to be gifted in mathematics. Since an early age I've always excelled in math; I was actually factoring and solving elementary Algebra problems by age 8 when most kids are doing arithmetic. Math and logic come naturally to me and I usually solve problems quickly and with minimal work.

As it turns out, doing so is not a practice ABeka encourages. They wanted to see every little step and sub-step of my math work. I would sit down and breeze through a test with 98% accuracy, and lose 10% because I "didn't show enough work". I can understand that, as the graders, they need to see some work between my beginning and ending steps, so I would always show my work at important intervals. But I didn't show enough, even though anyone looking at what I did could tell what I was doing. I could combine three steps in my head and turn what they deemed an eight-step problem into a four or three step problem just by my normal way of solving problems. I wouldn't condense the steps too much, though, and would usually include a step or two more than I personally needed to just for good measure. But I would, consistently, get scrawled red-ink notes on my tests informing me that I wasn't showing enough work because doing work, showing the important steps of the solution, and getting the correct answer wasn't good enough. If I were shortening 10 step problems to four step problems I might see their point, but, like I said, I wasn't doing that. I can recall multiple instances where I actually lost points for shortening a four-step problem down to a two or three step problem.

Wanting to see the steps a student uses to solve a math problem is reasonable, but ABeka wasn't insisting I be reasonable. They were insisting I memorize and regurgitate their step-by-step solutions.

Throughout ABeka's math courses, I found myself painfully trying to find extra sub-steps to write down, so that I would actually get full credit for my work. There were many tests where I actually lost more points to not showing enough work than to making mathematical errors.

Unfortunately, this is very typical of ABeka. They don't encourage creativity and ingenuity; they encourage memorization and regurgitation. Understanding math isn't important, following steps 1, 2, and 3 is. That's a horrible way to teach math. At the end of such a class, a student will not have learned anything life-applicable, they will have learned how to memorize math steps. And, as a math major, I'm here to tell you that that flat out doesn't work. Ask any math student or math professor at any university and they'll tell you that that learning method isn't worth beans to students.

Another issue I have with their math department is that they only offer three real years of traditional, consecutive math study, their fourth year is devoted exclusively to consumer math –- if you opt to take math at all. That's fine, I have nothing against people taking consumer math, but not everyone benefits from it. No disrespect to anyone who has taken consumer math, but anyone who plans on majoring in something science, engineering, or math related does not want to waste an entire year on consumer math. It isn't going to help them in anything. If they're going to be an engineer, they obviously have the math skills necessary to understand consumer math as it comes in life. What they need for their careers is a strong understanding of trigonometry and calculus. They have so much math they'll need to study they can't afford to spend a year not progressing towards higher math.

But ABeka doesn't offer calculus. The highest level of math they offer is a hybrid trigonometry/advanced geometry/pre-calculus class. If you could just go down to the local community college and get your calculus class that way it wouldn't be so bad, but, as I discussed earlier, that isn't exactly an option. ABeka won't accept college classes, so you're stuck with what they offer unless you double up and do ABeka's full school load in addition to calculus at college. Possible, yes. Reasonable? Not really.

If you'd hoped, in lieu of getting any calculus, to get a good, solid trigonometry foundation (which, believe me, you future engineers and mathematicians will need), you're in for a disappointment. Their hybrid trigonometry/advanced geometry/pre-calculus class is, in my opinion, the worst math class they offer. They try to cram too much into one class, and the class as a whole is devoid of direction. You have a semester of trigonometry, then you have a semester of geometry, and at the end they announce that you're ready for calculus. I've taken college pre-calculus, and it's nothing like what their pre-calculus is. So for the record, you're not usually ready for calculus by the time you're done with that class. If you have the option of doing so without hurting your planning, take a real pre-calculus class at your community college your senior year of high school. It'll get you better prepared for actual calculus and it'll help keep your mind in shape during your year of vacation from math at ABeka.

Also, I'd go so far as to say that their hybrid trigonometry/advanced geometry/pre-calculus textbook(s) are the worst textbooks I have ever used. The books are confusing, very poorly organized, vaguely worded, and sometimes just ramble about nothing that make sense. A good math textbook will be something (if you go on in a field related to math) that you reference in later years when you have a question on that topic. I myself have referenced every math textbook I've used since Algebra II -- except their trigonometry/geometry one.

Along the lines of bad math classes, trigonometry/advanced geometry/pre-calculus isn't the only bad one, so are Algebra I and II. The Algebra series is almost the same subject both years, as best I could tell. Half of Algebra II is contained in Algebra I, just a little differently, which logically means that either their Algebra II moves back to overlap traditional Algebra I or their Algebra I moves ahead to overlap traditional Algebra II. Anyone familiar with ABeka definitely knows the answer to that. (For non-Abeka’ers, Algebra I moves ahead. ABeka never reaches backward for anything. When in doubt push too fast and slow down later. That is their motto.) Students don't get the opportunity to take math gradually and let it grow on them; they get it shoved into their face. There's a difference between memorizing math and understanding math. Students can memorize math in the same way they memorize poems, and then forget it a couple years (or weeks) later. Math, taught properly, shouldn't be like that. What good is it that way?

The algebra textbooks are nothing to brag about either. They're poorly organized and confusing. Woe to the student, or mother, who doesn't have the DVDs and opts to learn the material straight from the book. I taught myself exclusively almost all of the math I learned in school through their 8th grade math level, but, once I hit their Algebra I textbook, it all came to a shuttering halt. I couldn't teach myself the material any more, and that prompted us to to sign up for their video program. Their math textbooks are good and I would recommend them up to 8th grade. After that they're horrible and I would recommend you look elsewhere.

(I've heard many other people voice the exact same thing about ABeka's textbooks. In the beginning I wondered if it was just my mom and I who didn't like the difference between ABeka's lower grade math books and their high school text books, but I've met a lot of people who agree. I've even had people e-mail me, after reading what I say, who say the exact same thing, "ABeka was great, right up until high school.")

For those who don't know me, and for those who do know me, let me remind you, I'm a math major. Math is what I do, math is what I understand, and math is what I've studied. I would confidently say that I'm more than qualified to speak on their math program. And doing so, I grade it a C. Sure it could be worse, but that's almost a failing grade. (I guess it's better than it sounds. A C is, after all, by ABeka's standards, about, what, an 85%?*)

* This is meant to be funny. ABeka students won't find this funny, though, because this is too close to reality to be funny.

Now, leaving the realm of math and going to the complete opposite side of the spectrum...

Their English program is somewhat insane. Each year's English class is basically two classes rolled into one. It was like they couldn't decide whether to focus on grammar or literature, so they just decided to get the best of both worlds and decided to do both. Looking back, I think that English was by far their most intense subject. There was always grammar homework to do, literature to read and comprehend, and poems to memorize. Constantly, constantly, constantly. Write this, memorize that, etc. Due to the amount of material covered, English had about twice the number of quizzes of any other subject. There were actually quite a few classes composed of nothing but a pile of 15-minute quizzes.

I'm all for students having good grammar and being able to write well because it's a necessary life skill. I think less highly of literature, but it has its merits. But ABeka needs to decide what they want to do with their English program. Forcing students to concurrently deal with two nearly full time subjects is just stupid. I can't help but notice, at my college, that the English Writing and English Literature classes are in completely separate categories, and I don't think that's by chance. One class. One subject. It works best that way. Someone should point that out to ABeka.

I don't know why the four years of high school English aren't split into two years of each subject. The fact that they try to teach grammar in English for all four years of high school is just weird. I mean, you don't need four years of English grammar. Eventually you need to concentrate on just writing (enough with the sentence diagrams already). But no. They try to fit the exact same material into each English class for four years. I think they should just split their classes up into two years of writing and two years of literature (or some other ratio). The writing classes would consist of learning to write, and the literature classes would consist of learning to comprehend literature and poem memorization. Each class would be object-oriented, and just maybe you wouldn't find yourself diagramming sentences going into your senior year. I have never heard of anyone else having to do that.

Overall, their English program seems to be aimless. You do four years of it, and at the end you've spent countless hours writing the same essays multiple times, diagramming the same sentences over and over, and memorizing of poems that, honestly, you don't remember a tenth of by the end. For a private school with their reputation, it sure is easy to go through their program and not improve your writing abilities. It could be argued I'm proof of that.

This brings up yet another subject I want to point out. ABeka is known for being tough, which isn't bad. Tough isn't a bad thing, in and of itself, and I personally like tough. My problem with ABeka is how tough they are in combination with how inflexible their schedules are. They don't give students homework to complete by the end of the chapter, or by the end of the week, rather, by every class the last assignments are due and new assignments are issued. There's no buffer period for students to manage. If you do all the homework and assignments for each class, every day is an exact repetition of the last.

In college, and I have report that this is similar in public schools, my workloads rise and fall in each subject over each week. Each day has different priorities and different subjects that need to be studied. In ABeka, it's the same thing every day. Every day you have to do x, y, and z, and it has to be done today so that tomorrow you can do the new and improved X, Y, and Z. Not only does it not allow for personal interruptions in life it gets very old very fast. If you're not a good "just grinding away at it" person, you'll get bored of ABeka in about a month. It'll become a seemingly endless, boring chore.

Like I said at the beginning, I only did three years of ABeka's high school program. I left at the start of my senior year. But hopefully, by now, you understand why I left. I didn't leave because I was a failing, lazy student. I left because they couldn't meet my needs. I needed math and computer classes; they didn't provide them and wouldn't accept college alternatives. Their grading was obnoxious and discouraged creativity and originality. Their English workloads were irritatingly heavy with no sense of direction or real accomplishment and distracted me from beneficial activities. And in general, I grew to simply loathe their classes.

I left Abeka a straight A student after three fairly miserable years and joined the ACAEA in my senior year, graduated half way through the year, and promptly started college.

On that note, going from ABeka's high school program to college was a huge change. And I have to say, in all honesty, ABeka's scholastic training didn't help a bit. Their environment was completely different from college. Nothing ABeka teaches or encourages by way of study habits and scholastic conditioning will be useful in any normal college. And nothing they say you'll need in college you actually will need in college. The teachers in ABeka's video lectures make the occasional remark about how you're going to need skill X or knowledge Y to survive in college and/or the rest of life, and nine times out of ten it's completely bogus. The exception is their Bible classes. Those are by far the most practical and best classes they offer.

In college, they're interested in creativity and ingenuity. They're concerned that you get the right answer, rarely how you got there. Your homework, if you even have any that is obligatory to turn in, is collected sporadically in chunks, allowing you to pick it up and do it at your own pace whenever you need to. The focus is to gain understanding and brainpower, and they're usually pretty relaxed about it.

In summary, here are my complaints about ABeka Academy. I've talked a lot, but this list summarizes the main points that I've talked about:

  1. ABeka will not accept college classes.
    • They don't offer calculus.
    • Their trigonometry/advanced geometry/pre-calculus math class is bad, and doesn't prepare you for when you eventually do take calculus.
    • Their algebra series is too aggressive.
  2. Their English program is heavy, time consuming, and redundant.
  3. Their overall teaching style is too anal and procedure oriented.
  4. They don't prepare you for real life, despite the fact they incessantly insist that they do.

So... These are just my own thoughts about ABeka, and I know that there are those who would disagree with my opinions. Some people aren't like myself. Some people like the hard workloads and "just do it" mentality of ABeka. That's fine, but those people are the minority, most other people don't fit well with ABeka, and I'd like for those people to know what they're getting into before they find it out the hard way.

How do you know if you're right for ABeka? If you're a casual, independent, questioning person, ABeka probably won't be a good fit. Conversely, if you like memorizing 15 20-line poems a year, having your homework dictated to you day by day, and taking only three real years of math, you probably will fit with ABeka. And that's fine. I'm not saying ABeka is morally evil, I'm just saying that I personally don't like them. And I think that a lot of other people, judging from ABeka's turnover rate, don't like them either, but don't know enough when they begin to know that.

But, ultimately, it's all about education. Never forget the primary function of school. School is to teach you knowledge and, most importantly, expand your understanding. Pick what works with your personality and educational mindset the best.

Implementation of Blowfish in C

This algorithm implementation is a part of my cryptography implementations project. The full project, along with licensing information and more detail, is hosted on GitHub.

Algorithm

This is an implementation of the Blowfish block cipher.

There are two steps to the cipher. First, five sets of tables are initialized using the user's key and the blowfish encryption algorithm itself (making the algorithm recursive). Second, the data is encrypted using the permutated tables initialized previously.

Code Documentation

  • void key_schedule(uchar user_key[], BLOWFISH_KEY *keystruct, int len)
    This generates an encryption key from a user-supplied key.
    • uchar user_key[]
      This is the user-supplied key.
    • BLOWFISH_KEY *keystruct
      This is the key structure that will be used to encrypt data later in the encryption functions.
    • int len
      This is the length, in bytes, of the key in the first parameter. It may be any value up to 448.
  • blowfish_encrypt(uchar in[], uchar out[], BLOWFISH_KEY *keystruct)
    blowfish_decrypt(uchar in[], uchar out[], BLOWFISH_KEY *keystruct)
    These functions encrypt and decrypt data, accordingly, using a Blowfish key structure.
    • uchar in[]
      This is the data to be encrypted, for the blowfish_encrypt() function, and the data to be decrypted for the blowfish_decrypt() function.
    • uchar out[]
      This is where to store the output encrypted data, for the blowfish_encrypt() function, and the output decrypted data for the blowfish_decrypt() function.
    • BLOWFISH_KEY *keystruct
      This is the key structure that is generated by the key_schedule() function (above). It is the same for both encrypted and decryption.

Usage

  1. Create the arrays to hold both input and output data for the encryption and/or decryption functions and a BLOWFISH_KEY structure.
  2. Call the key_schedule() function with the key, the BLOWFISH_KEY structure, and the length of the key in bytes.
  3. To encrypt data, call the blowfish_encrypt() function passing the array with the plaintext, the array to hold the output ciphertext, and the key structure.
  4. Do decrypt data, call the blowfish_decrypt() function passing the array with the ciphertext, the array to hold the output plaintext, and the key structure.

Code

Notes

In this implementation, all the initial P-Box and S-Box constants are stored in static memory location and copied to temporary memory locations for use in the key initialization step. This is because the S-Box and P-Box values will be altered during the key initialization for each key. If the implementor wishes to encrypt data using multiple keys in the same session, then the key initialization function must be called more than once, and each time it is called it must start with the same constant values.

Assuming the developer only needs to use one Blowfish key, this code could be slightly optimized to just use the one set of S/P-Boxes. These factors are only of practical concern for extremely computationally-weak machines (specialized hardware).

Cryptanalysis of the Blowfish algorithm itself to date has yielded but a few minor flaws, placing Blowfish as one of the best 64-bit block ciphers in existence. However, 64-bit block ciphers can leak information about the plaintext and should not be used if possible. So although no reasonable attacks exist against Blowfish itself, its 64-bit block size make it less than undesirable in the modern cryptographic world.

Implementation of Base 64 in C

While not a cryptographic algorithm, this implementation is a part of my cryptography implementations project because it's a handy encoding. The full project, along with licensing information and more detail, is hosted on GitHub.

Algorithm

This is an implementation of Base64 encoding.

Base64 is an encoding scheme that allows binary data to be represented as text. It accepts a bit string of any length, splits it up into chucks of 6 bits, and replaces each chunk with its corresponding value from the list of characters:
ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/
When the input is not an even multiple of 6 bits, the character '=' is appended to the output as padding as needed.

Since the input has 8 bits of significant data and the output has 6 significant bits of data (there are 26=64 characters in the array above), the input to output ratio is very close to 3:4.

Documentation

  • void base64_encode(unsigned char in[], unsigned char out[], int len)
    This encodes raw data to Base64.

    • unsigned char in[]
      This contains the data to be encoded.
    • unsigned char out[]
      This will contains the output. The array should be larger than the input by a scale of 4:3, with a two character buffer.
    • int len
      This is the length, in bytes, of the input.
    • int newline_flag
      This is a flag, which can be set to true or false, to indicate whether or not the function should insert a newline in the base64 output every 76 characters. The technical specification for Base64 calls for this value, but this was based on technical standards/difficulties of the past and isn't always desirable. By setting it to a non-zero value, a newline character will be added every 76 output characters (to wrap it in a rough rectangle shape), if it is set to 0 then the output will be one long string.
  • base64_decode(unsigned char in[], unsigned char out[], int len)
    This function decodes Base64 code into its original form.

    • unsigned char in[]
      This contains the Base64 data to be decoded.
    • unsigned char out[]
      This is the output array, it should be at least 3/4 the length of the input data, with an extra character of buffer.
    • int len
      This is the length of the input Base64 data.
    • Note: There is no need to include a newline flag for the decoding function, as it automatically parses out newline characters.

Usage

  1. First create/allocate two arrays to contain your original and encoded data.
  2. Determine the length of the data you wish to encode. Pass the input data, the array to contain the output, and the length of the data as arguments to the base64_encode() function.
  3. When you wish to decode the data, use the base64_decode() function. It works the same way, except the data gets decoded.

Code

Notes

This is the traditional base64 encoding scheme. The internet version of base64, in order to be URL friendly, replaces the last two characters of the substitution array, "+" and "/", with "*" and "-", respectively.

Update (7-26-06): Thanks to Christoph Otto for fixing a NULL termination bug.

Implementation of AES in C

This algorithm implementation is a part of my cryptography implementations project. The full project, along with licensing information and more detail, is hosted on GitHub.

Algorithm

This is an implementation of the AES block cipher in 128, 192, and 256 bit modes, where the bit size corresponds to the key length. The algorithm encrypts plaintext in block sizes of 128 bits.

Documentation

  • KeySchedule(unsigned char key[], unsigned int w[])
    This function takes the generated key (128, 192, or 256 bits in length) and generates a key schedule to use in encryption.

    • unsigned char key[]
      Must contain 16, 24, or 32 bytes of data to be used as the key.
    • unsigned int w[]
      Must be 60 32-bit integers in size. This will be the outputted key schedule.
    • int keysize
      Must be the size of the key in bits, limited to the values 128, 192, or 256.
  • aes_encrypt(unsigned char in, unsigned char out, unsigned int key[], int keysize)
    aes_decrypt(unsigned char in, unsigned char out, unsigned int key[], int keysize)
    These functions encrypt and decrypt data, respectively.

    • unsigned char in[]
      The plaintext to be encrypted. The array must be 16 bytes in size.
    • unsigned char out[]
      The output ciphertext. The array must be 16 bytes in size.
    • unsigned int key[]
      The "w" array key schedule from the KeySchedule() function.
    • int keysize
      Ensure it's the same value as the "keysize" value in KeySchedule() function.

Code Usage

  1. Call the KeyExpantion() function with the encryption key you want to use, the key schedule array, and the number of bits in length of the key.
  2. To decrypt data, call the aes_encrypt() function with the input plaintext array, an array to hold the output ciphertext, and the size of the original key in bits (same as the value passed to the KeyExpantion() function).
  3. To decrypt data, call the aes_decrypt() function with the input ciphertext array, an array to hold the output plaintext, and the size of the original key in bits (same as the value passed to the KeyExpantion() function).

Code

Notes

I've only taken basic steps towards optimizing this, so the implementation is fairly slow.

This implementation has not been designed to resist side-channel attacks.

There are a couple extra simple functions included in this code, printstate(), print_rnd_key(), and print_arry(), that are strictly debugging functions. These are not a part of the AES implementation and may be removed, they only exist to aid in debugging the code should someone try to alter the code. I used them excessively when originally writing this implementation.

Implementation of SHA-256 in C

This algorithm implementation is a part of my cryptography implementations project. The full project, along with licensing information and more detail, is hosted on GitHub.

Algorithm

This is an implementation of the SHA-256 hash algorithm.

Code Documentation

  • SHA256_CTX
    A MD5 structure that will hold all hash-related data and calculations as the hash is calculated.
  • SHA256_init(SHA256_CTX *ctx)
    Initializes the SHA256_CTX object.
  • SHA1_update(SHA256_CTX *ctx, unsigned char data[], int len)
    Once an object has been created and initialized, the data to be hashed must be added. Due to practical limitations, it may not be optimal (or possible) to add all the data to the SHA256 hash in one data chunk, so the function inputs, stores, and calculates data as it is received, allowing the data to be added in as many chunks as necessary.

    • unsigned char data[]
      This is the data to be added to the hash.
    • int len
      This is the length, in bytes, of the data in the "data" array.
  • SHA256_final(SHA256_CTX *ctx, unsigned char hash[])
    Finalize and output the hash.
    • unsigned char hash[]
      This is the array to store the output hash, which is 32 bytes long.

Code Usage

  1. Create an SHA256_CTX object.
  2. Initialize it with sha256_init().
  3. Read some/all of the data to hash into an array, calculate the size of the data, and add it to the hash with sha256_update().
  4. Repeat the previous step for all the data you want to hash.
  5. Finalize and output the hash with sha256_final().

Repeat steps (2) to (5) for as many hashes as you want to calculate.

Code

Notes

The 32-bit words (aka, unsigned integers) used in the code assume little endian byte ordering. The SHA-256 specification uses the big endian byte order, so some byte-reversals are made when copying data into and out of integers in this code.

Note that this only provides the 256-bit variant of the SHA-2 specification.

This algorithm has only basic optimizations, and does not have very fast benchmarks. This algorithm has passed testing against numerous test vectors, including all official vectors.

Implementation of (Triple) DES in C

This algorithm implementation is a part of my cryptography implementations project. The full project, along with licensing information and more detail, is hosted on GitHub.

Algorithm

This is an implementation of the DES and 3 DES block ciphers. 3DES (is simply the DES algorithm iterated three times and sometimes referred to as Triple DES. This algorithm encrypts plaintext in block sizes of 8 bytes.

Code Documentation

For DES:

  • void key_schedule(unsigned char key[], unsigned char schedule[][6], unsigned int mode)
    This function generates a multi-dimensional key schedule from a user-supplied key, the key schedule will be used for encryption.

    • unsigned char key[]
      Must contain 8 bytes of data to be used as the key.
    • unsigned int schedule[][6]
      Must be 16 arrays of 6 bytes each. This will contain the final key output.
    • unsigned int mode
      This value should be set to appropriate the macro-defined ENCRYPT or DECRYPT value.
  • void des_crypt(unsigned char in[], unsigned char out[], unsigned char key[][6])
    This function both encrypts and decrypts text using the key schedule.

    • unsigned char in[]

      This contains the plaintext/ciphertext to be encrypted/decrypted. It must contain 8 bytes of data. Padding may be necessary if it is the last block of the plaintext.
    • unsigned char out[]
      This contains the encrypted/decrypted ciphertext/plaintext output. It must be 8 bytes in size.
    • unsigned int key[][6]
      The "schedule" array from the key_schedule() function.

For 3DES:

  • void three_des_key_schedule(unsigned char key[], unsigned char schedule[][16][6], unsigned int mode)
    • unsigned char key[]
      This array must contain 24 bytes of data to be used as the encryption key.
    • unsigned int schedule[][16][6]
      Must be 3 arrays each with 16 arrays of 6 bytes each.
    • unsigned int mode

      Set this equal to the macro-defined ENCRYPT or DECRYPT values.
  • three_des_crypt()
    function must be called, the same function both encrypts or decrypts the data.

    • unsigned char in[]
      Must contain 8 bytes of data to be encrypted/decrypted.
    • unsigned char out[]
      Must be 8 bytes in size to hold the encrypted/decrypted data.
    • unsigned int key[][16][6]

      The "schedule" array from three_key_schedule() function.

Code Usage

For DES:

  1. Generate an 8 byte key. Note that only the seven most significant bits of each byte will actually be used.
  2. Use the key_schedule() function to generate a key schedule from the eight byte key.
  3. Use the des_crypt() function to encrypt your plaintext in blocks of 8 bytes. (You will likely have to pad your last block of plaintext.) The output is the ciphertext.
  4. To decrypt the ciphertext, switch the "mode" argument for des_crypt() and pass said function the ciphertext as input.

For 3DES:

  1. Generate a 24 byte key. Note that only the seven most significant bits of each byte will actually be used.
  2. Use the three_des_key_schedule() function to expand the key into a key schedule.
  3. Use the three_des_crypt() function to encrypt your plaintext in blocks of 8 bytes. (You will likely have to pad your last block of plaintext.) The output is the ciphertext.
  4. To decrypt the ciphertext, switch the "mode" argument for three_des_crypt() and pass said function the ciphertext as input.

Code

Notes

This implementation adheres fully to the official DES specification and includes the Initial Permutation and Inverse Initial Permutation steps that are often neglected for convenience due to their lack of cryptographic purpose.

This is an amateur implementation of DES. It has benchmarked to be fairly slow and has not been designed to be resistant to any sort of side-channel attacks.

Implementation of SHA-1 in C

This algorithm implementation is a part of my cryptography implementations project. The full project, along with licensing information and more detail, is hosted on GitHub.

Algorithm

This is an implementation of the SHA-1 hash algorithm.

Documentation

  • SHA1_CTX
    A MD5 structure that will hold all hash-related data and calculations as the hash is calculated.

  • SHA1_init(SHA1_CTX *ctx)
    Initializes the SHA1_CTX object.

  • SHA1_update(SHA1_CTX *ctx, unsigned char data[], int len)
    Once an object has been created and initialized, the data to be hashed must be added. Due to practical limitations, it may not be optimal (or possible) to add all the data to the SHA1 hash in one data chunk, so the function inputs, stores, and calculates data as it is received, allowing the data to be added in as many chunks as necessary.

    • unsigned char data[] -- This is the data to be added to the hash.
    • int len -- This is the length, in bytes, of the data in the "data" array.
  • SHA1_final(SHA1_CTX *ctx, unsigned char hash[])
    Finalize and output the hash.
    • unsigned char hash[] -- This is the array to store the output hash. It must be at least 16 bytes in size.

Code Usage

  1. Create an SHA1_CTX object.
  2. Initialize it with sha1_init().
  3. Read some/all of the data to hash into an array, calculate the size of the data, and add it to the hash with sha1_update().
  4. Repeat the previous step for all the data you want to hash.
  5. Finalize and output the hash with sha1_final().

Repeat steps (2) to (5) for as many hashes as you want to calculate.

Code

Notes

The 32-bit words (which in this case are unsigned integers) used in the code use little endian byte ordering. The SHA-1 specification uses the big endian byte order, so some byte-reversals are made when copying data into and out of integers in this code.

This algorithm has not been well optimized, although some general attempts have been made to that effect. This algorithm has passed numerous test vectors (including all official ones) successfully.

This algorithm can hash data up to 264 bits (2,147,483,648 gigabytes) in length.

It is worth noting that SHA-1 is no longer considered a perfectly secure hash algorithm. It is recommended that a hash algorithm such as Whirlpool or RIPE-MD, or even SHA-1 with double the number of standard rounds, be used in when security is critical.

Implementation of MD5 in C

This algorithm implementation is a part of my cryptography implementations project. The full project, along with licensing information and more detail, is hosted on GitHub.

Algorithm

This is an implementation of the MD5 hash algorithm.

Documentation

  • MD5_CTX
    A MD5 structure that will hold all hash-related data and calculations as the hash is calculated.
  • md5_init(MD5_CTX *ctx)
    Initializes the MD5_CTX object.
  • md5_update(MD5_CTX *ctx, unsigned char data[], int len)
    Once an object has been created and initialized, the data to be hashed must be added. Due to practical limitations, it may not be optimal (or possible) to add all the data to the MD5 hash in one data chunk, so the function inputs, stores, and calculates data as it is received, allowing the data to be added in as many chunks as necessary.

    • unsigned char data[] -- This is the data to be added to the hash.
    • int len -- This is the length, in bytes, of the data in the "data" array.
  • md5_final(MD5_CTX *ctx, unsigned char hash[])
    Finalize and output the hash.
    • unsigned char hash[] -- This is the array to store the output hash. It must be at least 16 bytes in size.

Usage

  1. Create an MD5_CTX object.
  2. Initialize it with md5_init().
  3. Read some/all of the data to hash into an array, calculate the size of the data, and add it to the hash with md5_update().
  4. Repeat the previous step for all the data you want to hash.
  5. Finalize and output the hash with md5_final().

Repeat steps (2) to (5) for as many hashes as you want to calculate.

Code

Notes

The 32-bit words (which in this case are unsigned integers) used in the code assume little endian byte ordering. The MD5 specification uses the big endian byte order, so some byte-reversals are made when copying data into and out of integers in this code.

This algorithm has not been well optimized, although some general attempts have been made to that effect. This algorithm has passed numerous test vectors (including all official ones) accurately.

This algorithm can hash data of lengths up to 264 bits (2,147,483,648 gigabytes).

Note, that MD5 is no longer considered a reasonably secure hash algorithm. It is recommended that a hash algorithm such as SHA-1 or SHA-2 be used instead for cryptographic applications.

Implementation of MD2 in C

This algorithm implementation is a part of my cryptography implementations project. The full project, along with licensing information and more detail, is hosted on GitHub.

Algorithm

This is an implementation of the MD2 hash algorithm. This algorithm can hash data of any given length.

Code Documentation

  • MD2_CTX
    A MD2 object that will hold all hash-related data and calculations as the hash is calculated.
  • md2_init(MD2_CTX *ctx)
    Initialize the MD2_CTX object.
  • md2_update(MD2_CTX *ctx, unsigned char data[], int len)
    Once an object has been created and initialized, the data to be hashed must be added. Due to practical limitations, it may not be optimal (or possible) to add all the data to the MD2 hash in one data chunk, so the function inputs, stores, and calculates data as it is received, allowing the data to be added in as many chunks as necessary.
    • unsigned char data[] -- This is the data to be added to the running hash context.
    • int len -- This is the length, in bytes, of the data in the "data" array.
  • md2_final(MD2_CTX *ctx, unsigned char hash[])
    Finalize and output the hash.
    • unsigned char hash[] -- This is the array to store the output hash. It must be at least 16 bytes in size.

Code Usage

  1. Create an MD2_CTX object.
  2. Initialize it with md2_init().
  3. Read some/all of the data to hash into an array, calculate the size of the data, and add it to the hash with md2_update().
  4. Repeat the previous step for all the data you want to hash.
  5. Finalize and output the hash with md2_final().

Repeat steps (2) to (5) for as many hashes as you want to calculate.

Code

Notes

This implementation assumes little endian byte ordering (as the MD2 standard states it should). This algorithm not only has not been optimized, although some general attempts have been made to that effect. This implementation of MD2 has been tested against numerous test vectors (including all official ones) and has proved to be accurate.

Note that MD2 is not considered a secure hash algorithm. It is recommended that a hash algorithm such as SHA-1 or SHA-2 be used, as MD2 is grossly outdated.