The core of symmetric encryption programs is the encryption routine itself. Most programs do not create their own encryption routine but instead use one of several routines that have been vetted and approved by the U.S. Government and academic cryptographers. You can download these routines like AES, along with others, like Blowfish, and examine them yourselves. They are fairly easily to incorporate into your program so with a moderate degree of programming skill you can almost write your own Government-standard encryption program. Perhaps. Yull doesn't use AES. For Yull, encryption is handled in two parts which relate to each other. The first is the setup, handled by the Yull class. Besides validating parameters and files, it utilizes the 8 options to determine how the file is encrypted or decrypted, as you will read below. Once the setup, which is fairly complex, is completed, the reads are submitted to the encryption class, Andromeda. This document (Parts 1 and 2) discusses how Yull works, with code examples. One of Andromeda's 60 routines is Blowfish but the rest are written by me.
One of the bases of modern cryptography is Kerckhoffs's principle, which states that "A cryptosystem should be secure even if everything about the system, except the key, is public knowledge." (Wikipedia).
But if the size of the key is fixed or within a small range, the integrity of the system might be compromised as that might be useful information as to which file is the key. For instance, BlowFish, a popular encryption protocol, uses keys up to 448 bits, or 56 bytes; AES, the Government-approved standard, uses a key up to 256 bits or 32 bytes, so that is definitely some help when trying to narrow down the range of likely keys. This key space, which is used in most other encryption programs, is not very large; and even if today (2015) it is relatively immune to a brute force attack, the trend is not good. If the key is stored on a disk, knowing the size or the size range might narrow down the key possibilities, assuming that the enemy has access to the entire contents of the disk.
Also, with AES, the encryption system most commonly used, you know the rounds (the number of times the data goes through the encryption routine) are between 4 and 20 (according to the Wikipedia page for AES, it's 10 cycles for a 128 bit key, 12 for 192 and 14 for 256 bit keys). Yull uses a variable number of rounds ranging from 1 to 150.
Other encryption programs, mainly those which rely on AES, add a fixed amount of dummy data (this is part of AES does), so you might also figure out how much dummy data is added. Also, the files are not read out of disk order (to my knowledge; I think Yull is the only encryption application which does this.)
First, the size of the Yull key is not fixed. It can be any file between 100 and 10,000 bytes. It could be a Word file or a text file or a system file. Yull encrypts the key internally during runtime before using it, so the randomness of the key is not an issue (but of course, the more randomness the better). Yull gives you the option to create your own keys but you don't have to. So with Yull, without additional knowledge it is impossible to even guess the size of the key, let alone where it is. Yull can create the key if you want but you can also select the file yourself.
Second, unlike other applications (I have done a brief survey of them but I can't validate this is 100% correct; just seems that way), Yull's encryption mechanism depends not only on the key but also on the eight options:
Users, by setting the options, can influence but not determine the values Yull uses:
The rounds (the number of times a read buffer is submitted to encryption) range from 1 to 150. If a file is 10,000 bytes long and the read size is 100, there are 100 reads. And with 100 reads, what are the rounds? There are 149100 (or 2.082701e+217, which is 2.08 times 10217) possible combinations to try, a number way too large to be meaningful. So in order to brute force decrypt the file you would have to try that many attempts, for starters.
I don't know what other encryption applications do, but Yull does not necessarily read input files in disk order. Disk order is how the file is accessed from the disk. What Yull does is break that. Yull examines how large the file is and, based on some inputs, determines the number of reads. This is the file size divided by the read buffer size (taking into account any remainder). If the file is 1000 bytes long and the read buffer is 100 bytes then there are 10 reads. Yull then determines the order in which these 100 byte chunks are accessed.
If there were two reads there would be 2 possible read orders (2! or 2 factorial, which 2 x 1). If there were 10 reads, there would be 10! (3,628,800) possible read orders (10x9x8x7x6x5x4x3x2x1) and if there were 50 reads, there would be 50! or
possible combinations of reads. So if you knew somehow there were 50 reads you would be facing that number of decryption attempts, but TIMES the number of array combinations (14950).
YULL uses the following logic regarding the key:
If the key is smaller than the read amount
YULL uses the key as it is. If the key is larger than the read amount (say, 100 bytes and the key is 150 bytes)
YULL starts with the key as it is, encrypts the data
rounds number of times, then writes the data out, then gets new data but at this time
YULL changes the key. It will take a new 100 byte segment from the key, encrypt with that and continue the process until the last read is completed.
If the key were 5000 bytes long, the read size 100 bytes, and file to be encrypted was 500,000 bytes long, there would be 5000 reads. There would be 5000 subkeys used, based on the supplied key:
Here's three 100 byte subkeys selected from the key 256-1.key:
The original key, 256 bytes long.
The first 100 bytes selected as the first subkey.
The bytes 1-101 selected as the second subkey.
The bytes 2-102 selected as the third subkey.
As you can see
YULL uses these subkeys to do the work of encryption. They are keys derived from the original key.
YULLallows the user to further obscure the parameters with the concept of "personal data." Personal data is a text string you can optionally include on the command line (and also in the GUI app). With the command line app, it is formatted like this:
PDATA="MY BIRTHDAY IS MARCH 10 AND MY SIGN IS CAPRICORN."
Like all the other command line arguments you must include it for both encryption and decryption.
With the GUI app, the Personal Data is just another input box on the Options tab.
YULL, if you do use personal data (and you don't have to; it just adds another huge layer of protection), the code processes the Personal Data like this:
string s = parameters.getPersonalData();
if (s == "" || s == null)
log.AppendLine(@"You did not add any personal data (PData). This means your key is encrypted with only the default value of your user name. We strongly suggest you add PData as that will afford you greater protection.");
s = Environment.User;
SHA512 sha = new SHA512CryptoServiceProvider();
byte bytes = new byte[s.Length * sizeof(char)];
System.Buffer.BlockCopy(s.ToCharArray(), 0, bytes, 0, bytes.Length);
Andromeda androm = new Andromeda();
//byte hash = sha.ComputeHash(bytes);
androm.Key = sha.ComputeHash(bytes);
int amount = key.Length / 512;
if (key.Length > 512)
if (key.Length % 512 != 0) amount++;
byte subs = new byte[amount];
if (key.Length %512 ==0)
for (int i = 0; i < amount; i++)
subs[i] = new byte;
System.Buffer.BlockCopy(key, i * 512, subs[i], 0, 512);
androm.inBuff = subs[i];
System.Buffer.BlockCopy(androm.inBuff, 0, key, i * 512, androm.inBuff.Length);
for (int i = 0; i < amount; i++)
if (i == amount - 1) subs[i] = new byte[key.Length % 512];
else subs[i] = new byte;
System.Buffer.BlockCopy(key, i * 512, subs[i], 0, i == amount - 1 ? key.Length % 512 : 512);
androm.inBuff = subs[i];
System.Buffer.BlockCopy(androm.inBuff, 0, key, i * 512, androm.inBuff.Length);
else //key under 512; just encrypt it as usual
androm.inBuff = key; ///this is what we are encrypting
//and when done copy the encrypted bytes back to the key
System.Buffer.BlockCopy(androm.inBuff, 0, key, 0, androm.inBuff.Length);
What this does is create a SHA512 hash of your personal data. SHA512 will create a 64 byte long hash string of the personal data. Yull then instantiates an Andromeda encryption object, sets the Andromeda key to the hash and the actual Yull key to the inBuff of Andromeda and encrypts the Yull key, following the usual rules of Andromeda. This way, if you have protected your Personal Data, even if the enemy gets your key and the encrypted file there is no way for them to brute force decrypt your data. This is because the key actually used is nothing like the key on the disk. Yull requires personal data. This data could be anything, like, "Hi, I'm Ron" or "My personal encryption personal data" etc. If there is no personal data, Yull enrypts the key with the defalt SHA512 hash (based on "").
The reason the key is limited to 10,000 bytes is that
addPDatatToKey encrypts the whole key in one pass and encrypting a large key, say, 4096 bytes, takes a long time. So, in the interests of speed, the key is limited to 10,000 bytes. (10,000 is a magic number; it could be 9001 or 10,199 or 57,001.)
A corporation could use one key for all it's employees and as long as each employee has their own Personal Data unlike all the others, each employee's data would not be decryptable by another employee.
In addition, Yull users 64 encryption functions which are called based on the key (see the Andromeda section below).
If the check boxes next to the Buff Size, Rounds or Dummy Data are checked (see Figure 3) then Yull will ignore those values and use the key to determine the respective values, using the Operation Mode as a guide, as well as the minimum and maximum amounts.
To recap: For other encryption programs, if you have the key, the encrypted file, and the program itself, you are on your way to getting the plaintext. But with Yull, that is far from enough as Yull also requires that the Options be correct. And where are the options stored? Yull lets you store them in external files but you don't have to. They could stored on a piece of paper in a drawer if that seems best. You may also encrypt your options. That key is never stored anywhere.
As Yull does far more work than other encryption programs it is somewhat slower and with the Operation Mode set to MAX it could be quite a bit slower. However, if it takes, say 3 seconds to encrypt (and decrypt) that is actually an additional safety feature in that brute force will take too long, sometimes tens of millions or billions of years.
If you have the key and the encrypted file, you will still not have any way to guess the read buffer size (and hence the number of reads) or the number of rounds for each read; nor will you know the amount of dummy data added to each read. You will also not know the read order.
By encrypting many times and with various combinations of the 55 encryption routines in Andromeda (the encryption class), is it common for Yull to encrypt a file with tens of millions, hundreds of millions, even hundreds of billions of encrypts. So, not only is there an enormous number of option parameter combinations, running to the quadrillions, there are also a possible several hundred billion encrypts (and decrypts) which, without the options and the key, all have to be tried in the correct order. This, I believe (but without mathematical proof), is a physical impossibility, regardless the number of GPU/Quantum computers put to the task.
Most encryption programs use some version of AES to handle the file encryption. Yull uses its own routines which are described in the Andromeda section below.
Yull Encryption Pro is a .NET 4.0 application written in C# using Visual Studio 2015. There are two executables: the GUI, named YullG and the console app, Yull. The executable, YullG, is a Windows-based, GUI application with three major components (classes) and a few minor helper classes. The console app has two classes and one helper class. For the GUI, the first class is the UI (user interface class) which handles user input, hosts the controls as WinForm controls, performs validation, manages options, and so forth.
This is the main screen: the File Tab.
Figure 1 The File Tab
You can see there are three menus and three tabs. The File tab has an Encrypt section, Decrypt section, several controls to display files and other information about them. Here it is after selecting the file 256C and encrypting it with the default key (created earlier).
Here's the tab examining the files to decrypt:
Next is the Options Tab:
Figure 2 The Options Tab
There are quite a few options but for encryption, they boil down to four: the buffer read size, the number of rounds, read order, and the amount of dummy data.
The UI does a lot of setup before starting the encryption process but eventually it will figure out the list of files to be worked on and then get to a file loop. In this case, there is only one file in the loop, 256-1, located in the z:\test\source folder. This is one of the test files I created during the coding process. Here are some of the contents of 256-1:
Figure 3 A partial hex dump of a test file before encryption
It's longer than this but I created it so I could easily determine during development if the encryption/decryption process succeeded or failed. This file is 12,288 bytes long.
The encryption process is initiated when the UI instantiates the Yull class. After passing the relevant parameters to Yull, the UI invokes the encryption start routine and from here, the Yull object takes over.
The Yull object continues with the setup. It validates again that the parameters make sense, that the source file exists and can be opened, that an output file can be created in the specified location and also if a key was selected, and if that key is valid, by performing a rudimentary test. If no key is selected, Yull will create a key of the specified length, with a minimum length of 100 bytes and maximum of 100,000 bytes. The user can select nearly any file as a key, there is no limit to the size or location as long as it is a local file and the key is not all of the same byte value or mostly 0x00.(This is only a suggestion to the user. In fact, since Yull encrypts the key before using it, the key file could be any file within the size limits. It's just my opinion that more randomness is better.)
Next Yull figures out the read buffer size. This is one of the four critical parameters that Yull uses to encrypt. As you can see from the values in Figure 2, there are several "Buff" size and "Round" size controls. These control how big of a read buffer Yull will create, hence how many reads, and also how many rounds per read (more on this in a bit). Additionally, there is also the Dummy Size option as well as the Read Order Pad.
As Yull needs to duplicate the encrypt parameters when decrypting, if the user elects to let Yull decide the buff size, rounds and dummy data amount, the only constant Yull can rely on to determine these values is the key, which Yull uses with simple math in conjunction with the Operation Mode (see Figure 2) as a guide, along with the values in the Buff Size, Max Buff and Min Buff controls. (The Operation Mode has four possible values, Normal, Max, and Fast and Neuro, all discussed in more detail later on). If the "Yull decides" check boxes aren't checked, Yull will use the values in those respective controls, along with the Operation Mode.
Once Yull has the read buffer size, it determines how many reads there will be from the file size by dividing one into the other. If the read size is 100 and the file size is 1000 there will be 10 reads. If the read size is 100 and the file size is 1001 there will be 11 reads.
After the number of reads is calculated (which includes the buff size) Yull creates an array of rounds. A round is a call to the encryption class, Andromeda, to begin the encryption process. When Yull knows how many rounds and how many reads, it will create an array of keys based on the supplied (or created) key. There is one key used per each round of encryption. If there are 100 reads and 100 rounds per read, there will be 10,000 keys created. In the encryption process, if the key is smaller than the read buffer, it is extended to the size of the read buffer, if larger, truncated to the read buffer size. The keys are always the size of the read buffer, in essence a one-time pad.
Yull creates an array of rounds, the number of rounds equals the number of reads. A round is pass through Andromeda. So if, for a particular read, the Rounds array value is 17, that read buffer will be submitted 17 times to Andromda for encryption. The rounds values are not the same. The first read might be encrypted 18 times; the second 49; the third 108, and so forth. The rounds can take any value from 4 to 120. The numbers of rounds are created using the Operation Mode and the other Rounds values.
As with the other options, this value is controllable by the user from the UI. OR, the user can let Yull decide based on the Operation Mode (Normal, Max, Fast and Neuro). Small buffers mean fewer encrypts but faster encryption. Larger buffers mean far more encryptions (they seem to scale asymptotically), but the trade off is a slower program. 250 billion of anything takes a while. The read buffer size determines the number of reads.Here's the read buffers, rounds and encrypts for the file 12,288 byte file 256-1 encrypted with the four operation modes:
The Yull class performs two other major actions, one before the encryption process starts and one during the encryption process. Based on the number of reads, Yull creates an array that number long and assigns a unique number to each element of that array with the aid of the Read Order option. The numbers are not sequential and have no relation to each other. They are created using key values and the mod function. They have no significance except that they are random and not close to each other in size. Yull then sorts that array (which is really a Dictionary object) by using this Dictionary object to instantiate a Sorted List object. Yull uses the ordinal of each element of the Sorted List to determine the read order for encryption. The read order is under partial control of the user by setting the Read Order value. This value is used in the calculation of the values added to the Dictionary object.
Here's part of the file pictured in Figure 4:
Figure 4 Original (disk) read order with each read 96 bytes long
In this case each read is 96 bytes long (0x60), and these are the first eight reads.
When Yull is determining the read order, it might get values like this:
Remember, the values have no other significance than a mechanism to permit sorting based on a key.
After processing by the Dictionary Object and the Sorted List Object they might be read like this:
7, 2, 8, 6, 5, 4, 1, 3
Note again, these values are simply derived from some simple math and key. There are otherwise irrelevant except that they are all unique. This means that Yull reads the 7th block of data first, process it and write it out, then the 2nd, then the 8th, then the 6th and so forth.
Figure 5 Sorted read order
And written out in this order.
But, before Yull submits this block of data to the encryption object, it adds in random values from a call to the .NET RNGCryptoServiceProvider, which is what Yull uses to create the key, if asked to do so.
The amount of dummy data to be added is either set by the user or by Yull. So now the block to be encrypted might look like this, where Yull has added 64 bytes of dummy data at the start of the read buffer:
Figure 6 Dummy Data prepended to a read buffer
If you were to encrypt the file again, the random data would be different. Of course the random data inserted into the blocks is always different. As Yull encrypts, the data is dispersed into the buffer and the dummy values will affect how other bytes are encrypted.
The amount of random data (dummy data) is determined either by the user or let to Yull to decide (see Figure 3).
The file is read in this order and written out in the read order.
After Yull finishes encrypting the file, it zeroes out all the buffers (arrays) it used, then deletes them, closes the open files and exits, returning to the UI object, which then updates the main UI form, writes some data out and continues with the next file if there is one. The process for decryption is similar.
The use of dummy data (which cannot be suppressed) means that that Yull ciphertext is, unlike earlier ciphers like RC4, immune from bit flipping attacks, in which tiny changes in the plaintext are used to figure out how to decrypt the ciphertext.
There are some other features of the UI object. You can manage your personal data (located in AppData\Local\YullEncryption . By default, your options, history and default password are stored here. There is nothing sacred about this; you can change all of it.
Besides YullG, the UI application, there's also Yull.exe, which is a console app.
Additionally, you can export your current options and file selections to a batch file so the same operations can be run as a cron job or other type of job, in DOS or Powershell.
You can elect to encrypt your options
Figure 9 The Options Password Dialog Box
And, as mentioned before, export your options and file selection for use by the console app, yull.exe:
Here is the flow of data from the UI object, to Yull, to Andromeda and back.
I have been a developer since the mid-1980s, starting with C, C++ and assembly language. I worked for Ashton-Tate (dBase), Chase (Chemical), Random House, Logitech, and AXA Financial. I moved from C and C++ to C# and VB.NET.
In 1985 I wrote a file format conversion program called
XWORD, which had a rudimentary encryption module, basically just using
ROL, ROR and XOR. XWORD was reviewed by PC Magazine in June 1986 as the best file format converter. And here I am back there again. I started working on Yull in 2008 for my own amusement. I
was interested to see how much I could scramble data and then unscramble it.
In 2013, after adding some features, I was curious as to how many encrypt functions were
called so I put a counter at the beginning of each encrypt function where the
code actually enters the body of the function. During a run with a 70K file. I
expected a few thousand but I got almost two billion.
This means to me that any brute force reverse process would have to deal with two billion decryptions, on top of the options.
Now while this very seems significant to me, it may not be for reasons I do not understand. I am hoping cryptographers will be interested in looking at my code and passing judgment.
Z:\test\source\256H to Z:\TEST\OUTPUT\256H.out Sequence passed NIST test for randomness read buffer size=500 Max Rounds = 120 Min Rounds = 20 *****ENCRYPT ENDS******** total number of encrypts=1939718342 number of encrypts per byte=27856 Total RunTime (hours:minutes:seconds:milliseconds)=00:07:45.831 There were 140 reads. There were a total of 12572 rounds. Average rounds per read = 89 Approx. Speed per round in milliseconds = 37 File Conversion Speed: Bytes Per Second (approx) = 149 Yull ends. Parameters: Source file: Z:\test\source\256H Output file: Z:\TEST\OUTPUT\256H.out Output Dir: Z:\TEST\OUTPUT Key file: Key Size: 511 MinRounds: 20 MaxRounds: 120 Operation Mode: MAX MaxBuffSize: 500 BuffSize: 500 MinBuffSize: 100 DummyDataSize: 60 UseDefaultFolder=False UserDefaultKey=True Yull Decides Buff Size=True Yull Decides Dummy Data=True Yull Decides Rounds=True Please note these parameters as they are needed to decrypt the file.
This file, 69,632 bytes long, went through 1,939,718,342 encryption functions.
For one file of about 600K I got over 250 billlion encrypts. At that point I thought this might be a bit more than an intellectual adventure so I decided then to add a UI front end to Yull and the result is the current program, YullG.exe.There are now two versions of
YULL: YullG, Yull, the console application.
For information on how the Andromeda class works, please click on the link just below.
Andromda: The Encryption Class