### Abstract

Digital signing is a mechanism for certifying the origin and the integrity of electronically transmitted information. In the process of digitally signing, additional information – called a digital signature – is added to the given document, calculated using the contents of the document and some private key. At a later stage, this information can be used to check the origin of the signed document. The mathematical base of the digital signing of documents is public key cryptography.

This work presents the theory behind digital signatures, signature schemes and attacks on signatures and provides a survey of application areas of the digital signing technology. Moreover, there are lab exercises developed in Mathlab, to reinforce the understanding of this technology.

### 1. Introduction

The Concise Oxford Dictionary (2006) defines cryptography as the art of writing or solving codes, however modern cryptography does not met this definition. Therefore, this work starts with a literature review defining some key concepts, like what cryptography and cryptographic system are and the different types of cryptographic system are presented. The other interesting and preliminary concept is the notion of cryptosystem functions which are also discussed in the introductory section. Furthermore, it is stated that public-key encryption represents a revolution in the field of cryptography, and this work poses some basic definitions on this topic trying to explain the theory behind. The rest of the literature review is concentrated on public key cryptography and it focuses on the theory behind digital signatures, signature schemes and attacks on signatures. And finally, the literature review presents a survey of application areas on digital signatures.

One part of the contribution of this work, is an overview of the secure hash standard (SHS) and implementation of the secure hash algorithm (SHA-1), required for use with digital signature algorithms. The main part though, is the implementation of AES and RSA by utilizing Mathlab. The code of all these implementations is thoroughly discussed and explained in this work. Moreover, a comparison is also presented subsequently.

### 2. Cryptography

The Greek words “krypt´os” standing for “hidden” and the word “l´ogos” that means “word”, are in essence the base from where the word cryptology was derived. As these words denote, cryptology can be best explained by the meaning “hidden word”. In this context, the original purpose behind cryptology is hiding the meaning of some specific combination of words which in turn would insure secrecy and confidentiality. This is a very limited viewpoint in today’s perspective and a wide range of security applications and issues now come under the term of cryptology (rest of the portion of this section will clarify this point of view). As field of mathematical science, Cryptology includes the study of both cryptanalysis as well as cryptography. On one hand, cryptography is a very broad term and represents any process used for data protection. On the other hand, the study of security related issues and the probabilities of breaking the cryptographic systems and a technique is known as cryptanalysis. By making reference to (Shirey, 2000), the field cryptanalysis can be best described as the “mathematical science that deals with analysis of a cryptographic system in order to gain knowledge needed to break or circumvent the protection that the system is designed to provide.” In simple words, cryptanalyst can be regarded as the opponent of the cryptographer i.e. he/she has to get around the security which cryptographer devised on his/her part.

(Buchmann, 2004) claims that a cryptographic system (or in short a cryptosystem) describes “a set of cryptographic algorithms together with the key management processes that support use of the algorithms in some application context.” This is a diverse explanation that includes all sorts of cryptographic algorithms as well as protocols. However, hidden parameters like cryptographic keys may or may not be used by a cryptographic system (Delfs, 2007). Similarly, participants of the undergoing communication may or may not share those secret parameters. Thus, cryptographic can be classified into following three types: a cryptographic system in which no secret parameters are employed (called an un-keyed cryptosystem); a cryptosystem which makes use of secret parameters and at the same time shares the parameters between the participants (known as a secret key cryptographic system); and a system that utilizes the secret parameters, but not sharing them with the participants (called a public key cryptographic system) (Shirey, 2000; Buchmann, 2004).

Cryptography aims at designing and implementing cryptographic systems and utilizing such systems which are secure effectively. The first a formal definition about the term cryptography dates from relatively past time. Back then, the approach known by the name “security through obscurity” was being used (Dent, 2004). There are a lot of examples based on this approach by which security of the system was improved by keeping internal working and design secret. Majority of those systems do not serve the purpose and security may well be violated. The Kerckhoffs’ principle is a very famous cryptographic principle which states that (Kerckhoffs, 1883):

“Except for parameters clearly defined to be secret, like the cryptographic keys, a cryptosystem must be designed in such a way as to be secure even with the case that the antagonist knows all details about the system”.

However, it might be noted that one important aspect is that a cryptosystem is perfectly securing theoretically grounds, but it may not remain the same when implemented practically. Different possibilities of generating attacks on security of such systems can arise while having the practical implementation (Anderson, 1994). Attacks which make use of exploitation of side channel information are the examples of such attacks. If a cryptosystem is executed, it can result in the retrieval of side channel information with unspecified inputs and outputs (Anderson, 1994). In encryption systems, the input is plaintext message plus the key, while the specific output is the cipher text. Thus, there are chances on information leakage. Power consumption, timing characteristics along with the radiation of all types are some examples in this regard. On the other hand, side channel attacks are the types of network attacks which extract side channel information. Since the mid 1990s there were many different possibilities have been found by the researchers in order to build up side channel attacks. A few examples in this regard are the differential power analysis (Bonehl, 1997), and fault analysis (Biham, 1997; Kocher, 1999) as well as the timing attacks (Kocher, 1996). It is a very practical statement that any computation performed on real computer systems represents some physical phenomena which can be examined and analyzed to provide information regarding the keying material being employed. Cryptography does not help to cope with this situation because of the inherent nature of this problem.

### 2.1 Cryptosystem functions

Other than the usual random bit generators as well as the hash functions, there are no secret parameters that are used in cryptosystem functions. These are the junketed functions that characterize the cryptographic system functions. In cryptographic functions, the elements used are usually one-way and it is difficult or almost impossible to invert them. This follows that it is easy to compute a cryptographic function whereas it is hard to invert the functions and also to compute the results of the relationships (Kerckhoffs, 1883). It is difficult to apply any mathematical method for inverting the cryptographic system functions in a way that will be coherent and meaningful. For example, a cryptographic system functions such as F: X → Y is easy to comfortably use mathematical knowledge to compute while it is hard to use the same to invert (Buchmann, 2004; Shirey, 2000).

There are many examples of one-way functions that we can use to demonstrate the meaning of the cryptosystems. In a situation where one has stored numbers on the cell phone, computation of the same is possible and easy due to the fact that the names are stored in an alphabetical manner (Garrett, 2001). If one inverts the relationship of these functions, it will be impossible to compute because the numbers are not arranged numerically in the storage phonebook. It is notable that a lot of other things that we do in daily life are comparable to cryptosystem function in the sense that you cannot invert or undo them. For example, if one breaks a glass, the process is one way because it is not possible for these pieces to be restored together again (Goldreich, 2004). Similarly, when one drops something into water, it is not practically possible to reverse the action of dropping this item (Mao, 2003). The English corresponding action would be to un-drop the item as opposed to picking it. Cryptosystem functions cannot be demonstrated as purely one-way and this is the branching point between cryptosystem functions and the real world of things and circumstances. The only one-way functions in mathematics can be exemplified by discrete exponentiation, modular power and modular square functions. Public key cryptography uses these functions in its operations but it has not been well documented whether they are really one-way or not. There has been debate in practice whether one-way functions really exist in the first place or not (Garrett, 2001). In the recent day cryptographic discussions a lot of care should be applied when referring to the one-way functions so as not to interfere or make false claims to the functional attributes of these parameters. There is a need to look for extra information and knowledge concerning one-way functions so that efficient and meaningful inversions are possible and mathematically coherent.

Therefore, functions such as F: X → Y is considered to be a one-way function (Koblitz, 1994; Schneier, 1996). This follows that if F can successfully and coherently inverted, the need for extra information is needed. This will hence bring the notion of the meaning of the other parameters in relation to F. Computer science uses the hash functions in its operations. This is because these functions are computable and generates output dependent on the input that was used (Katz, 2007; Koblitz, 1994).

### 3. Digital signatures

The public-key encryption presents a revolution in the field of cryptography and until its invention the cryptographers had relied completely on common, secret keys in order to achieve confidential communication (Smart, 2003). On the contrary, the public-key techniques, allow for the parties to communicate privately without the requirement to decide on a secret key in advance. While the concept of private-key cryptography is presented as two parties agree on a secret keyk which can be used (by either party) for both encryption and decryption; public-key encryption is asymmetric in both these respects (Stinson, 2005). Namely, in public-key encryption:

- One party (the receiver) generates a pair of keys (pk, sk), where pk is called the public key and ps is the private key,
- The public key is used by a sender to encrypt a message for the receiver, and
- The receiver uses the private key to decrypt that message.

There three parts of information form part of public key certificate:

- Some naming information
- A Public key
- Digital signatures (this can be one or more)

Encryptions and digital signatures were introduced to make the web transactions secure and manageable. The use of cryptographic techniques was applied to enhance and provide security layer such that the encrypted information and files would remain secure and confidential. Very frequently, a digital signature is mistaken with the inverse of a public-key encryption, but this is not entirely true. In the history, a digital signature could be obtained by reversing, but today in the majority of the situations this process would be impossible to be performed.

Basically, a digital signature is a form of a mathematical scheme for signifying the genuineness of a digital message. A valid digital signature would provide a proof to the person that receives the message or the document that these information is indeed created by a specified sender. Moreover, it would prove that message or the document was not altered during the transportation. Digital signatures are usually used for software distribution or mainly money transactions, where it is very important to detect the possibility of forgery.

As a part of the field in asymmetric cryptography, it might be noted that a digital signature is somehow equivalent of the traditional handwritten signatures. On the other hand, in order to be effective, a digital signature should be correctly implemented. Another very important concept is the notion of non-repudiation. This means that if somebody signs a document by using a digital signature, they can not say that it was not signed by them, even though their private key remains as a secret. On the other hand, there is a time stamp, so that even if the private key of a sender is compromised in future, the digital signature will remain valid. Examples of such messages are:

- electronic mail
- contracts
- messages sent via some cryptographic protocol

A digital signature usually is comprised of:

- An algorithm for producing a key. This algorithm would find a private key by chance from all the possible private keys available. Then it will output that private key with a matching public key.
- A signing algorithm that, given a message and a private key, produces a signature.
- A signature authenticating algorithm that, given a message, public key and a signature, it will accept or reject the message.

Primary, a signature produced from a fixed message and a private key verifies that the genuineness of that message is ok, by means of the matching public key. Then, it has to be computationally infeasible to make an appropriate signature for a party that doesn’t have the private key

### 4. Algorithms

### 4.1. Introduction to SHS

This section provides an overview of the secure hash standard (SHS) and implementation of the secure hash algorithm (SHA-1), required for use with digital signature algorithms.

SHA-1 is used for computing a compressed version of a message or a data file. If that data has a length smaller than 264 buts, then the output will be 160-bit and is called a message digest. The message digest used for an input to the Digital Signature Algorithm (DSA). This algorithm will verify the signature for the message. Signing the message digest instead of the originall message itself, might advance the effectiveness of the procedure. This is since the message digest is usually much slighter in size than the original message. Very important is that the same hash algorithm should be used by both the verifier and the digital signature creator.

The usage of the SHA-1 with the DSA can be presented as follows:

Interesting for SHA-1 is that it is computationally impossible to discover a message which matchs to a given digest. Moreover, it is also impossible to find two dissimilar messages which create an identical message digest.

### 4.2. Implementation of SHA-1

The following functions were implemented for the SHA-1 algorithm:

Name of source file: secure_hash_algorithm.m. Function in the source file: secure_hash_algorithm (message). This function takes an input a string of characters.

Example: “Hello, How are you? How is it going on?” – Output is the message digest, the hash value of the message. Thus, the hash value of the above message is “F418F52AE6DC208599F91191E6C40FA876F33754”.

Name of source file: arithematic_shift_operations.m. Function in the source file: arithematic_shift_operations (number, position, op). The inputs are:

- number: it is a hexadecimal large number of any size. The number is represented in base 16 and is stored as a string. Ex: ‘FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF’
- position: the number of positions to be shifted by. It is a decimal number in base 10.
- Op: it is the type of operation done. Inputs are ‘SRA’ -> shift right arithematic and ‘SLA’ -> shift left arithematic.

For example, the function:

- arithematic_shift_operations(‘FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF’, 3, ‘SRA’) would return ‘1FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF’, and
- arithematic_shift_operations(‘FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF’, 3, ‘SLA’) would return ‘FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF8’.
- Name of source file: bi2hex.m. Function in the source file: bi2hex (number). The input to this function is a vector of ones and zeros and the result is a hexadecimal output represented in string. For example, for the input “Number = [1 1 1 1]” bi2hex (Number) returns ‘F’ and for “Number = [1 1 1 1 0 0 0 1 ]” bi2hex (Number) returns ‘F1’.
- Name of source file: hex2bi.m. Function in the source file: hex2bi (number). The input to this function is a number stored in form of a string in base 16 and the result is a vector containing the binary representation of input string. For example, for the input “Number = ‘F’ ”, hex2bi (Number) returns “[1 1 1 1]” and for “Number = ‘F1’ “, bi2hex (Number) returns “[1 1 1 1 0 0 0 1]”.
- Name of source file: hexadecimal_big_number_adder.m. Function in the source file: hexadecimal_big_number_adder (number_one, number_two). The inputs to this function are numbers stored in hexadecimal string format. Output is the result, a hexadecimal string and carry, a decimal number. After using this function, it has to be checked if the carry is generated, Incase if it is generated then the carry has to be appended in the beginning to the result. For example:

Number_one = ‘FFFFFFFF’

Number_two = ‘EEEEEEEE’

[result, carry] = hexadecimal_big_number_adder (Number_one, Number_two)

Result = ‘EEEEEEED’ , carry = 1;

Hence the real sum is Result = strcat(dec2hex(0), Result); this results to ‘1EEEEEEED’

Name of source file: hexadecimal_big_number_subtractor.m. Function in the source file: hexadecimal_big_number_subtractor(number_one, number_two). The inputs to this function are numbers stored in hexadecimal string format. Output is the result, a hexadecimal string and sign, a decimal number. If sign is -1, then the result generated is a negative number else is a positive number. . For example:

Number_one= ‘EEEEEEEE’

Number_two= ‘FFFFFFFF’

[result, sign] = hexadecimal_big_number_subtractor(Number_one, Number_two)

Result = ‘11111111’

Sign = -1.

Name of source file: hexadecimal_big_number_multiprecision_multiplication.m. Function in the source file: hexadecimal_big_number_multiprecision_multiplication(multiplicand, multiplier). The input is a multiplicand stored in string format is a hexadecimal number. And so is multiplier. The output is a result and is stored in form of a string. For example:

multiplicand= ‘EEEEEEEE’

multiplier= ‘FFFFFFFF’

hexadecimal_big_number_multiprecision_multiplication(multiplicand, multiplier)

result is ‘EEEEEEED11111112’

Name of source file: comparision_of.m. Function in the source file: comparision_of(number_one, number_two, index). This function compares two numbers in hexadecimal format stored in form of strings. Always input index as decimal 1. Therefore, it:

Returns 1 if Number_one > Number_two,

Returns 0 if Number_one = Number_two, and

Returns -1 if Number_one < Number_two.

For example, if

Number_one= ‘EEEEEEEE’

Number_two= ‘FFFFFFFF’, the result would be:

comparision_of(Number_one, Number_two, 1) returns -1.

Name of source file: hexadecimal_big_number_modular_exponentiation.m. Function in the source file: hexadecimal_big_number_modular_exponentiation (base, exponent, modulus). This function calculates (power(base, exponent) % modulus). Here the input base, exponent and modulus are hexadecimal strings of any size. For example:

Base = ‘FFF’

Exponent = ‘EEE’

Modulus = ‘AAAA’

hexadecimal_big_number_modular_exponentiation (Base, Exponent, Modulus) returns ‘8BAB’

Name of source file: hexadecimal_big_number_multiplicative_inverse.m. Function in the source file: Z = hexadecimal_big_number_multiplicative_inverse(number_one, number_two). This function returns multiplicative inverse of number_two modulo number_one. If az = 1 (mod m) then z is the multiplicative inverse of a mod m. Here “number_one = m”, “number_two = a”, “number_one = ‘FFFF’ ”, “number_two = ‘1235’ “ andresult is ‘634D’, which in turn is the multiplicative inverse of number_two.Hence :

(result * number_two) mod number_one = 1

- Name of source file: hexadecimal_big_number_test_for_primality.m. Function in the source file: hexadecimal_big_number_test_for_primality(number). The input to this function is an ODD number stored in hexadecimal format as a string. This function returns 1 if the input is a prime and returns -1 if input is composite.
- Name of source file: power_of_two_conversion_to_hexadecimal.m. Function in the source file: power_of_two_conversion_to_hexadecimal(power). The input is the number, the power to which two has to be raised to. It is a decimal number and the output is a hexadecimal number in form of string. For example, power_of_two_conversion_to_hexadecimal(4) returns ‘10’ i.e 16 in decimal system.
- Name of source file: hexadecimal_big_number_division.m. Function in the source file: hexadecimal_big_number_division (dividend, divisor). This function returns quotient and remainder both in hexadecimal string format. The inputs to this function are strings of hexadecimal format. This function uses other two functions in turn which are defined in source file Get_multiplier.m, multiplication_by_single_digit_multiplier.m.
- Name of source file: remove_leading_zeros.m. Function in the source file: remove_leading_zeros (number). This function takes number in hexadecimal string format as input and removes the leading zeros in the string and returns it. For example, if “Number = ‘000000012345’ “, then the function returns ‘12345’.

Some of the most prominent functions are presented in Appendix A.

### 4.3. Introduction to MD5

The MD5 Message-Digest Algorithm is a extensively utilised in cryptographic hash functions. Basically this is the case for cryptographic hash functions with a 128-bit (16-byte) hash value. MD5 is used in many security applications, and in addition it is frequently used to check data integrity. An MD5 hash is typically expressed as a 32-digit hexadecimal number.

The following figure represents a schematic view of the MD5 Message-Digest Algorithm.

### 4.4. Implementation of MD5

This algorithm would compute MD5 hash function for files. For example, if as input is given the d = md5(FileName), then the function md5() will computes the MD5 hash function of the file specified in the string FileName. This function will returns it as a 64-character array dwhere d is the digest. The following methodology that the MD5 algorithm was implemented:

- Initially, the function Digestis called.
- This function would read the whole file, and will make it uint32 vector

FileName = ‘C:md5InputFile.txt’

[Message,nBits] = readmessagefromfile(FileName);

Then, it would append a bit in the last one that was read from that file:

BytesInLastInt = mod(nBits,32)/8;

if BytesInLastInt

Message(end) = bitset(Message(end),BytesInLastInt*8+8);

else

Message = [Message; uint32(128)];

end

Consequetly, it will append the zeros:

nZeros = 16 – mod(numel(Message)+2,16);

Message = [Message; zeros(nZeros,1,’uint32′)];

And a bit length of the original message as uint64, such as the lower significant uint32 first:

Lower32 = uint32(nBits);

Upper32 = uint32(bitshift(uint64(nBits),-32));

Message = [Message; Lower32; Upper32];

The 64-element transformation array is:

T = uint32(fix(4294967296*abs(sin(1:64))));

The 64-element array of number of bits for circular left shift:

S = repmat([7 12 17 22; 5 9 14 20; 4 11 16 23; 6 10 15 21].’,4,1);

S = S(:).’;

Finally, the 64-element array of indices into X can be presented as:

idxX = [0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 …

1 6 11 0 5 10 15 4 9 14 3 8 13 2 7 12 …

5 8 11 14 1 4 7 10 13 0 3 6 9 12 15 2 …

0 7 14 5 12 3 10 1 8 15 6 13 4 11 2 9] + 1;

The initial state of the buffer is consisting of A, B, C and D. such as:

A = uint32(hex2dec(‘67452301’));

B = uint32(hex2dec(‘efcdab89’));

C = uint32(hex2dec(’98badcfe’));

D = uint32(hex2dec(‘10325476’));

The message is reshaped, such as:

Message = reshape(Message,16,[]);

The look between the blocks, such that X is an extraction of the next block:

for iBlock = 1:size(Message,2)

X = Message(:,iBlock);

The buffer states are stored as:

AA = A;

BB = B;

CC = C;

DD = D;

The buffer is transformed by utilizing the X block from above, and the parameters from S, T and idxX

k = 0;

for iRound = 1:4

for q = 1:4

A = Fun(iRound,A,B,C,D,X(idxX(k+1)),S(k+1),T(k+1));

D = Fun(iRound,D,A,B,C,X(idxX(k+2)),S(k+2),T(k+2));

C = Fun(iRound,C,D,A,B,X(idxX(k+3)),S(k+3),T(k+3));

B = Fun(iRound,B,C,D,A,X(idxX(k+4)),S(k+4),T(k+4));

k = k + 4;

end

end

The old buffer state is also being added:

A = bitadd32(A,AA);

B = bitadd32(B,BB);

C = bitadd32(C,CC);

D = bitadd32(D,DD);

end

The message digest is being formed the following way:

Str = lower(dec2hex([A;B;C;D]));

Str = Str(:,[7 8 5 6 3 4 1 2]).’;

Digest = Str(:).’;

The subsequent functionality is performed by the following operations:

function y = Fun(iRound,a,b,c,d,x,s,t)

switch iRound

case 1

q = bitor(bitand(b,c),bitand(bitcmp(b),d));

case 2

q = bitor(bitand(b,d),bitand(c,bitcmp(d)));

case 3

q = bitxor(bitxor(b,c),d);

case 4

q = bitxor(c,bitor(b,bitcmp(d)));

end

y = bitadd32(b,rotateleft32(bitadd32(a,q,x,t),s));

And the bits are rotated such as:

function y = rotateleft32(x,s)

y = bitor(bitshift(x,s),bitshift(x,s-32));

The sum function is presented as:

function sum = bitadd32(varargin)

sum = varargin{1};

for k = 2:nargin

add = varargin{k};

carry = bitand(sum,add);

sum = bitxor(sum,add);

for q = 1:32

shift = bitshift(carry,1);

carry = bitand(shift,sum);

sum = bitxor(shift,sum);

end

end

A message is being read frm a file, such as:

function [Message,nBits] = readmessagefromfile(FileName)

[hFile,ErrMsg] = fopen(FileName,’r’);

error(ErrMsg);

Message = fread(hFile,inf,’ubit32=>uint32′);

fclose(hFile);

d = dir(FileName);

nBits = d.bytes*8;

Lastly, the auto test function is the following:

function md5autotest

disp(‘Running md5 autotest…’);

Messages{1} = ”;

Messages{2} = ‘a’;

Messages{3} = ‘abc’;

Messages{4} = ‘message digest’;

Messages{5} = ‘abcdefghijklmnopqrstuvwxyz’;

Messages{6} = ‘ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789’;

Messages{7} = char(128:255);

CorrectDigests{1} = ‘d41d8cd98f00b204e9800998ecf8427e’;

CorrectDigests{2} = ‘0cc175b9c0f1b6a831c399e269772661’;

CorrectDigests{3} = ‘900150983cd24fb0d6963f7d28e17f72’;

CorrectDigests{4} = ‘f96b697d7cb7938d525a2f31aaf161d0’;

CorrectDigests{5} = ‘c3fcd3d76192e4007dfb496cca67e13b’;

CorrectDigests{6} = ‘d174ab98d277d9f5a5611c2c9f419d9f’;

CorrectDigests{7} = ’16f404156c0500ac48efa2d3abc5fbcf’;

TmpFile = tempname;

for k=1:numel(Messages)

[h,ErrMsg] = fopen(TmpFile,’w’);

error(ErrMsg);

fwrite(h,Messages{k},’char’);

fclose(h);

Digest = md5(TmpFile);

fprintf(‘%d: %sn’,k,Digest);

if ~strcmp(Digest,CorrectDigests{k})

error(‘md5 autotest failed on the following string: %s’,Messages{k});

end

end

delete(TmpFile);

disp(‘md5 autotest passed!’);

### 4.4.1 Results

This algorithm is tested with the input: university of Portsmouth department of electronic and computer engineering. This was written on the file: “C://md5InputFile.txt”. The outpus results are as in the following fugures:

Textual description of the output results follows:

### OUTPUT

FileName = C:md5InputFile.txt Running md5 autotest… FileName =

C:md5InputFile.txt

1986621045 1769173605 1864399220 1867522150 1836282994 1752462703 1885692960 1836348001 544501349 1696622191 1952671084 1768845170 1851859043 1868767332 1953853549 1696625253 1852401518 1769104741 26478

1: 3129b41fa9e7159c2a03ad8c161a7424

FileName =

C:md5InputFile.txt

1986621045 1769173605 1864399220 1867522150 1836282994 1752462703 1885692960 1836348001 544501349 1696622191 1952671084 1768845170 1851859043 1868767332 1953853549 1696625253 1852401518 1769104741 26478

2: 3129b41fa9e7159c2a03ad8c161a7424

FileName =

C:md5InputFile.txt

1986621045 1769173605 1864399220 1867522150 1836282994 1752462703 1885692960 1836348001 544501349 1696622191 1952671084 1768845170 1851859043 1868767332 1953853549 1696625253 1852401518 1769104741 26478

3: 3129b41fa9e7159c2a03ad8c161a7424

FileName =

C:md5InputFile.txt

4: 3129b41fa9e7159c2a03ad8c161a7424

FileName =

C:md5InputFile.txt

5: 3129b41fa9e7159c2a03ad8c161a7424

FileName =

C:md5InputFile.txt

6: 3129b41fa9e7159c2a03ad8c161a7424

FileName =

C:md5InputFile.txt

7: 3129b41fa9e7159c2a03ad8c161a7424 md5 autotest passed!

### 4.5. Introduction to Caesar cipher

The Caesar cipher in cryptography, is in essence a shift cipher. It represents as one of the simplest and most widely known encryption methodologies. The Caesar cipher is a kind of substitution cipher. It means that each letter in a given plaintext is replaced by another letter. This is done due shifting by some fixed number of positions down the alphabet. Julius Caesar was the first to use this ci