MD5 Introduction:
MD5 is an English "Message-Digest Algorithm Five", in the 1990s by Mit's computer science laboratory and RSA Data Security Inc, the initial MD2, MD3 and MD4 development evolution came. "Message-Digest" generally refers to the "Message" hash transform, which is to convert an arbitrary length byte string into a certain long integer. Please note that I use the word "byte string" instead of "string", because this transformation is only related to the value of the byte, it is independent of the character set or coding method, that is, many friends ask MD5 to confine the Chinese characters. The principle.
MD5 transforms any length of "byte string" into a 128bit large integer, and it is an irreversible string transform algorithm. SOLMINAL is that it is the source code of the MD5 algorithm full, so that anyone can understand The detailed algorithm of MD5 is described, but it is absolutely no one to convert a string of string to the original string from the MD5 algorithm. From the principle of math, it is because the original string has endless, this is a bit Like the math function of the reverse function.
The typical application of MD5 is to generate FingerPrint (fingerprints) for a Message to prevent tampering. For example, you write a word in a readme.txt file, and generate a MD5 value for this readme.txt and record it, then you can spread this file to others, others modify the file Anything, you will find the difference between the two files when you recall MD5, so that the file has been changed early. If there is another third party certification body, use MD5 to prevent "reliability" of the author, this is the so-called digital signature application.
MD5 can also be widely used in encryption and decryption techniques. In many operating systems, the user's password is saved in MD5 values (or similar algorithms). When the user is logged in, the system is to put users. The input password is calculated into an MD5 value, then compares the MD5 value of the initial password saved in the system, and the system is actually not "know" what the user's password is. Some hackers cracked this password method is a method called "running dictionary", that is, the so-called violent cracking method or exhaustive method. The method of obtaining the dictionary has two kinds, one is a list of "mentally mini passwords" to do a password, and the other is the MD5 program, which is generated by the MD5 program. Value, then retrieve in this dictionary with the MD5 value of the target.
Even if the maximum length of the password is assumed to be 8, the password can only be uppercase or lowercase letters and numbers, then "26 26 10" is also 62 valid password characters, so the number of items that are arranged in combination It is p (62, 1) p (62, 2) .... P (62, 8), which is also the same as an astronomical number, store this dictionary, the TB level disk group, and this There is also a premise that the password MD5 value of the target account can be obtained.
Application of MD5 algorithm in crack:
In the encryption protection of the software, MD5 is an encryption algorithm that is often used, but because the MD5 algorithm is an inverse algorithm, all software can only use the MD5 algorithm as an encrypted intermediate step, such as a username MD5 transformation, the result is another reversible encryption transform, the transform results are registration code. When doing registration machines, you must also use MD5 to enlay conversion, then evolve with the inverse algorithm of the second algorithm to derive the original username. Specifically: We set the user name to strRname, the registration code is strRegno, then if the author of the shared software uses the following algorithm as the registration algorithm of his own software: 'IF MD5 = MD5 (strRegno) REGISTER Successful "Else" Register unsuccessful "then can write the registration machine as long as the software adopts the MD5 algorithm, but if the author uses the following algorithm: 'IF MD5 (StrRegno) = MD5 (Strname) THEN" If the Register Successful "else" register unsuccessful "', then I want to connect the Software Author you must find the serial number of the registered user by the authors you must obtain the registered user. Therefore, for the crack, as long as the software's registration algorithm is used, MD5 is enough. The characteristics of MD5 code are also very obvious, and it is easy to discover when tracking. If the software uses an MD5 algorithm, the following four constants will inevitably use when data is initialized:
A = 0x01234567
B = 0x89abcdef
C = 0xfedcba98
D = 0x76543210
If constant is constant, it may be a deformed MD5 algorithm or not an MD5 algorithm. The memory is displayed in memory:
01 23 45 67 89 AB CD EF Fe DC ... 32 10 a total 16 bytes
--------------------------------------------
MD5 algorithm description:
Step 1: Increase the fill
Increase the padding to make the data length (Bit as units) model 512 is 448. If the data length is exactly the mold 512 is 448, it is 1-512, which is 1-512, is 1-512, is 1-512, adding 512 filling bits. The first bit is 1, the rest is 0.
Step 2: Replenishment length
Convert data length to a value of 64bit, if the length of the data that can be represented by more than 64bit, the value retains the last 64bit, which is increased to the previously filled data, so that the last data is 512bit integral times. That is, 16 times the integer multiple of 32bit. In RFC1321, 32bit is called a word.
Step 3: Initialization variables:
Used 4 variables, which are A, B, C, D, all of which are 32 bit long. Initialized to:
A: 01 23 45 67
B: 89 AB CD EF
C: FE DC BA 98
D: 76 54 32 10
Step 4: Data processing:
First define 4 auxiliary functions:
F (x, y, z) = xy v not (x) z
G (x, y, z) = xz v y NOT (z)
H (x, y, z) = x xor y xor
I (x, y, z) = y xor (x v not (z))
Where: XY represents the bit bit and X V y represented a bit position or, NOT (X) represents the bitwise reflusions. XOR represents a bitmap or.
The x, y, z of the function is 32 bit.
Define a number of arrays that need to be used: T (I), I value 1-64, T (i) equal to 4294967296 times of ABS (SiN (I)), i is an arc. Assuming the data length after the first three steps is 32 * 16 * nbit
Step 5: Output:
The last obtained ABCD is the output result, a total of 128bit. A is low, D is a high level.
The implementation of the MD5 algorithm in programming:
Let's take a look at how to implement MD5 algorithm in C, Delphi, and VB
C language example:
--------------------------------------------
* /
#ifndef prototypes
#define prototypes 0
#ENDIF
Typedef unsigned char * pointer;
Typedef unsigned short int uint2;
Typedef unsigned long int uint4;
#if protoypes
#define proto_list (list) List
#ELSE
#define proto_list (list) ()
#ENDIF
---------- Md5.h ----------------------------
Typedef struct {
Uint4 state [4];
Uint4 count [2];
UNSIGNED Char Buffer [64];
} MD5_CTX;
Void MD5init Proto_List ((MD5_CTX *));
Void MD5UPDATE PROTO_LIST
((MD5_CTX *, Unsigned CHAR *, UNSIGNED INT);
Void MD5Final Proto_List ((unsigned char [16), md5_ctx *));
※※※※※※※※※ ※ ※※※※※※※※※※※※※※※※※※※※※※
#include "global.h"
#include "md5.h"
#define S11 7
#define s12 12
#define s13 17
#define s14 22
#define s21 5
#define s22 9
#define s23 14
#define s24 20
#define s31 4
#define s32 11
#define s33 16
#define s34 23
#define s41 6
#define s42 10
#define s43 15
#define s44 21
Static void MD5Transform Proto_List ((uint4 [4), unsigned char [64]));
Static void Encode Proto_List
((unsigned char *, uint4 *, unsigned int));
Static Void Decode Proto_List
((Uint4 *, unsigned char *, unsigned int));
Static void MD5_Memcpy Proto_List ((Pointer, Pointer, Unsigned Int);
Static void MD5_MEMSET Proto_List ((Pointer, INT, Unsigned Int);
Static unsigned charphar padding [64] = {
0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
/ * Define F g H i to four courses
#define f (x, y, z) ((x) & (y)) | ((~ x) & (z)))))))
#define g (x, y, z) ((x) & (z)) | ((Y) & (~ z))))
#define h (x, y, z) ((x) ^ (y) ^ (z))
#define i (x, y, z) ((y) ^ ((x) | (~ z))))))
#define rotate_left (x, n) (((x) << (n)) | ((x) >> (32- (n)))))))
#define FF (A, B, C, D, X, S, AC) {/
(a) = f ((b), (c), (d)) (x) (UINT4) (AC); /
(a) = rotate_left ((a), (s)); /
(a) = (b); /
}
#define GG (A, B, C, D, X, S, AC) {/
(a) = g ((b), (c), (d)) (x) (UINT4) (AC); /
(a) = rotate_left ((a), (s)); /
(a) = (b); /
}
#define HH (A, B, C, D, X, S, AC) {/
(a) = h ((b), (c), (d)) (x) (UINT4) (AC); /
(a) = rotate_left ((a), (s)); /
(a) = (b); /
}
#define II (A, B, C, D, X, S, AC) {/
(a) = I ((b), (c), (d)) (x) (UINT4) (AC); /
(a) = rotate_left ((a), (s)); /
(a) = (b); /
}
/ * Start MD5 calculation
Void MD5Init (Context)
MD5_CTX * Context;
{
CONTEXT-> count [0] = context-> count [1] = 0;
/ * The four constants are defined here, that is, the four characteristics we have just said.
Context-> State [0] = 0x67452301;
Context-> State [1] = 0xEfcdAb89;
CONTEXT-> State [2] = 0x98badcfe;
Context-> State [3] = 0x10325476;
}
Void Md5Update (Context, Input, Inputlen)
MD5_CTX * Context;
Unsigned char * input;
Unsigned int inputlen;
{
Unsigned Int I, Index, Partle;
Index = (unsigned int) ((CONTEXT-> COUNT [0] >> 3) & 0x3F);
IF ((context-> count [0] = (uint4) Inputlen << 3)) <((uint4) inputlen << 3))
CONTEXT-> COUNT [1] ;
Context-> count [1] = ((uint4) Inputlen >> 29);
Partlen = 64 - Index; if (Inputlen> = Partle) {
MD5_MEMCPY
((Pointer) & context-> buffer [index], (Pointer) Input, Partle;
MD5Transform (context-> state, context-> buffer);
For (i = partlen; i 63 MD5Transform (Context-> State, & Input [i]); INDEX = 0; } Else i = 0; MD5_MEMCPY (Pointer & Context-> Buffer [Index], (Pointer) & INPUT [i], Inputlen-i); } Void Md5Final (Digest, Context) Unsigned char digest [16]; MD5_CTX * Context; { UNSIGNED Char Bits [8]; Unsigned int index, padlen ENCODE (Bits, Context-> Count, 8); Index = (unsigned int) ((CONTEXT-> COUNT [0] >> 3) & 0x3F); Padlen = (INDEX <56)? (56 - INDEX): (120 - index); MD5UPDATE (Context, Padding, Padlen); MD5UPDATE (Context, Bits, 8); ENCODE (Digest, Context-> State, 16); MD5_MEMSET ((Pointer) Context, 0, SizeOf (* Context)); } Static Void Md5Transform (State, Block) Uint4 state [4]; UNSIGNED Char Block [64]; { Uint4 a = state [0], b = state [1], c = state [2], d = state [3], x [16]; Decode (X, Block, 64); / * First round cycle * / FF (A, B, C, D, X [0], S11, 0xD76AA478); / * 1 * / FF (D, A, B, C, X [1], S12, 0xE8C7B756); / * 2 * / FF (C, D, A, B, X [2], S13, 0x242070dB); / * 3 * / FF (B, C, D, A, X [3], S14, 0XC1BDCEEE); / * 4 * / FF (A, B, C, D, X [4], S11, 0xF57c0FAF); / * 5 * / FF (D, A, B, C, X [5], S12, 0X4787C62A); / * 6 * / FF (C, D, A, B, X [6], S13, 0xA8304613); / * 7 * / FF (B, C, D, A, X [7], S14, 0xFD469501); / * 8 * / FF (A, B, C, D, X [8], S11, 0x698098D8); / * 9 * / FF (D, A, B, C, X [9], S12, 0x8B44F7AF); / * 10 * / FF (C, D, A, B, X [10], S13, 0xFFFFF5BB1); / * 11 * / FF (B, C, D, A, X [11], S14, 0X895CD7BE); / * 12 * / FF (A, B, C, D, X [12], S11, 0x6B901122); / * 13 * / ff (D, A, B, C, X [13], S12, 0xFD987193); / * 14 * / FF (C, D, A, B, X [14], S13, 0XA679438E); / * 15 * / FF (B, C, D, A, X [15], S14, 0X49B40821); / * 16 * / / * Second round cycle * / GG (A, B, C, D, X [1], S21, 0XF61E2562); / * 17 * / GG (D, A, B, C, X [6], S22, 0XC040B340); / * 18 * / GG (C, D, A, B, X [11], S23, 0X265E5A51); / * 19 * / GG (B, C, D, A, X [0], S24, 0XE9B6C7AA); / * 20 * / GG (A, B, C, D, X [5], S21, 0XD62F105D); / * 21 * / GG (D, A, B, C, X [10], S22, 0x2441453); / * 22 * / GG (C, D, A, B, X [15], S23, 0XD8A1E681); / * 23 * / GG (B, C, D, A, X [4], S24, 0XE7D3FBC8); / * 24 * / GG (A, B, C, D, X [9], S21, 0X21E1CDE6); / * 25 * / GG (D, A, B, C, X [14], S22, 0XC33707D6); / * 26 * / GG (C, D, A, B, X [3], S23, 0xF4D50D87); / * 27 * / GG (B, C, D, A, X [8], S24, 0x455A14ED); / * 28 * / GG (A, B, C, D, X [13], S21, 0XA9E3E905); / * 29 * / GG (D, A, B, C, X [2], S22, 0XFCEFA3F8); / * 30 * / GG (C, D, A, B, X [7], S23, 0X676F02D9); / * 31 * / GG (B, C, D, A, X [12], S24, 0x8D2A4C8A); / * 32 * / / * Third round loop * / HH (A, B, C, D, X [5], S31, 0xFFFA3942); / * 33 * / HH (D, A, B, C, X [8], S32, 0x8771F681); / * 34 * / HH (C, D, A, B, X [11], S33, 0x6D9D6122); / * 35 * / HH (B, C, D, A, X [14], S34, 0xFDE5380C); / * 36 * / HH (A, B, C, D, X [1], S31, 0XA4BEEA44); / * 37 * / HH (D, A, B, C, X [4], S32, 0x4BDECFA9); / * 38 * / HH (C, D, A, B, X [7], S33, 0XF6BB4B60); / * 39 * / HH (B, C, D, A, X [10], S34, 0XBEBFBC70); / * 40 * / HH (A, B, C, D, X [13], S31, 0x289B7EC6); / * 41 * / HH (D, A, B, C, X [0], S32, 0XEAA127FA); / * 42 * / HH (C, D, A, B, X [3], S33, 0xD4EF3085); / * 43 * / HH (B, C, D, A, X [6], S34, 0X4881D05); / * 44 * / HH (A, B, C, D, X [9], S31, 0xD9D4D039); / * 45 * / HH (D, A, B, C, X [12], S32, 0xE6DB99E5); / * 46 * / hh (C, D, A, B, X [15], S33, 0x1FA27CF8); / * 47 * / HH (B, C, D, A, X [2], S34, 0XC4AC5665); / * 48 * / / * Fourth round cycle * / II (A, B, C, D, X [0], S41, 0XF4292244); / * 49 * / II (D, A, B, C, X [7], S42, 0x432AFF97); / * 50 * / II (C, D, A, B, X [14], S43, 0XAB9423A7); / * 51 * / II (B, C, D, A, X [5], S44, 0XFC93A039); / * 52 * / II (A, B, C, D, X [12], S41, 0X655B59C3); / * 53 * / II (D, A, B, C, X [3], S42, 0x8F0CCC92); / * 54 * / II (C, D, A, B, X [10], S43, 0xffeff47d); / * 55 * / II (B, C, D, A, X [1], S44, 0X85845DD1); / * 56 * / II (A, B, C, D, X [8], S41, 0X6FA87E4F); / * 57 * / II (D, A, B, C, X [15], S42, 0XFE2CE6E0); / * 58 * / Ii (C, D, A, B, X [6], S43, 0XA3014314); / * 59 * / II (B, C, D, A, X [13], S44, 0X4E0811A1); / * 60 * / II (A, B, C, D, X [4], S41, 0XF7537E82); / * 61 * / II (D, A, B, C, X [11], S42, 0XBD3AF235); / * 62 * / II (C, D, A, B, X [2], S43, 0x2AD7D2BB); / * 63 * / II (B, C, D, A, X [9], S44, 0XEB86D391); / * 64 * / State [0] = a; State [1] = B; State [2] = C; State [3] = D; MD5_MEMSET ((Pointer) X, 0, SizeOf (x)); } Static void Encode (Output, Input, Len) Unsigned char * OUTPUT; Uint4 * input; Unsigned int Len; { UNSIGNED INT I, J; For (i = 0, j = 0; j Output [j] = (unsigned char) (INPUT [I] & 0xFF); Output [J 1] = (Unsigned Char) ((INPUT [I] >> 8) & 0xFF); OUTPUT [J 2] = (unsigned char) ((INPUT [I] >> 16) & 0xFF); OUTPUT [J 3] = (Unsigned Char) ((INPUT [I] >> 24) & 0xFF); } } Static void Decode (Output, Input, Len) Uint4 * output; Unsigned char * input; Unsigned int Len; { UNSIGNED INT I, J; For (i = 0, j = 0; j ((UINT4) INPUT [J 2]) << 16) | ((uint4) INPUT [J 3]) << 24); } Static void MD5_Memcpy (Output, Input, LEN) Pointer Output; Pointer INPUT; Unsigned int Len; { Unsigned Int i; For (i = 0; i } Static void MD5_MEMSET (Output, Value, Len) Pointer Output; Int value; Unsigned int Len; { Unsigned Int i; For (i = 0; i (CHAR *) OUTPUT [I] = (char) value; } ---------------- C code end ---------- Implement MD5 algorithm in VB ------------------------------------------ The module source code is as follows: Private const offset_4 = 4294967296 # Private const Maxint_4 = 2147483647 Private State (4) As long Private Bytecounter As Long Private Bytebuffer (63) as byte PRIVATE CONST S11 = 7 PRIVATE CONST S12 = 12 PRIVATE CONST S13 = 17 PRIVATE CONST S14 = 22 Private const S21 = 5 Private const S22 = 9 Private const S23 = 14 Private const S24 = 20 Private const S31 = 4 Private const S32 = 11 Private const S33 = 16 Private const S34 = 23 Private const S41 = 6 Private const S42 = 10 Private const S43 = 15 Private const S44 = 21 Property Get Registera () AS String Registera = State (1) End Property Property Get Registerb () AS String Registerb = state (2) End Property Property Get Registerc () AS String Registerc = State (3) End Property Property Get Registerd () AS String Registerd = state (4) End Property Public Function MD5_String_Calc (SourceString As String) AS STRING MD5init Md5Update lenb (Str Congest, vbfromunicate), StringtoArray (SourceString) MD5Final MD5_STRING_CALC = GetValues END FUNCTION Public Function MD5_FILE_CALC (Infile As String) AS STRING ON Error Goto Errorhandler Gosub Begin Errorhandler DigestFileTohexStr = "" EXIT FUNCTION Begin: DIM Fileo As INTEGER Fileo = freefile Call Filelen (Infile) Open Infile for Binary Access Read As #fileo MD5init Do While Not Eof (Fileo) Get #fileo, Bytebuffer IF LOC (Fileo) Bytecounter = bytecounter 64 MD5Transform Bytebuffer END IF Loop Bytecounter = bytecounter (Lof (Fileo) MOD 64) Close #fileo MD5Final MD5_FILE_CALC = GetValues END FUNCTION Private function StringtoArray (Instring as string) as byte () DIM I as integer, bytbuffer () as Byte Redim ByTBuffer (Lenb (Strconv (Instring, Vbfromunicode))) BYTBUFFER = STRCONV (Instring, Vbfromunicode) StringtoArray = bytbuffer END FUNCTION Public function getValues () AS STRING GetValues = LongtoString (State (2)) & longtostring (State (3)) & longtoString (State (4)) END FUNCTION Private function longtoString (Num as long) AS STRING Dim A as Byte, B as Byte, C as Byte, D as Byte A = NUM AND & HFF & HFF & IF a <16 killing = "0" & hex (a) else longtostring = HEX (a) B = (Num and & HFF00 &) / 256 IF B <161 LongtoString = LongtoString & "0" & hex (b) else longtostring = longtostring & hex (b) C = (Num and & HFF0000) / 65536 IF C <16 Then LongtoString = longtostring & "0" & hex (c) else longtostring = longtostring & hex (c) IF Num <0 THEN D = (Num and & H7f000000) / 16777216) OR & H80 & Else D = (Num and & HFF000000) / 16777216IF D <16 Then LongtoString = LongtoString & "0" & HEX (d) Else LongtoString = LongtoTString & HEX (D) END FUNCTION Public Sub Md5init () Bytecounter = 0 State (1) = unsignedtolong (1732584193 #) State (2) = unsignedtolong (4023233417 #) State (3) = unsignedtolong (2562383102 #) State (4) = unsignedtolong (271733878 #) End Sub Public Sub Md5Final () DIM DBLBITS AS DOUBLE, PADDING (72) AS BYTE, LNGBYTESBUFFERED AS Long Padding (0) = & h80 DBLBITS = BYTECUNTER * 8 LNGBYTESBUFFERED = Bytecounter MOD 64 IF lngbytesbuffered <= 56 Then Md5Update 56 - lngbytesbuffered, padding else md5update 120 - Bytecounter, Padding Padding (0) = unsignedtolong (dblbits) and & HFF & HFF & Padding (1) = unsignedtolong (dblbits) / 256 and & HFF & HFF & Padding (2) = unsignedtolong (dblbits) / 65536 and & HFF & HFF & HFF & HFF & Padding (3) = unsignedtolong (dblbits) / 16777216 and & HFF & HFF & HFF & HFF & HFF & HFF & HFF & HFF & HFF & HFF & HFF & HFF & HFF & HFF & HFF & HFF & HFF & HFF & HFF & HFF & HFF & HFF & HFF & HFF & HFF & HFF & HFF & HFF & HFF & HFF & HFF & HFF & HFF & HFF & HFF & HFF & HFF & HFF & HFF & HFF & HFF & HFF & HFF & HFF & HFF & HFF & HFF & HFF & HFF & HFF & Padding (4) = 0 Padding (5) = 0 Padding (6) = 0 Padding (7) = 0 MD5UPDATE 8, PADDING End Sub Public Sub MD5Update (InputBuffer () AS BYTE) DIM II AS INTEGER, I AS Integer, J AS Integer, K AS Integer, LNGBufferremaining As Long, LNGREM As Long lngbufferedBytes = bytecounter mod 64 LNGBufferRemaining = 64 - lngbufferedbytes Bytecounter = bytecounter Inputlen IF infutlen> = lngbufferremaining then For ii = 0 to lngbufferremaining - 1 Bytebuffer (LNGBUFFEREDBYTES II) = InputBuffer (II) Next II MD5Transform Bytebuffer LNGREM = (Inputlen) MOD 64 For i = lngbufferremaining to infutlen - II - LNGREM STEP 64for J = 0 to 63 Bytebuffer (j) = inputbuffer (i j) NEXT J MD5Transform Bytebuffer Next i lngbufferedBytes = 0 Else I = 0 END IF Fork = 0 to Inputlen - I - 1 Bytebuffer (LNGBUFFEREDBYTES K) = InputBuffer (i K) Next K End Sub Private Sub MD5Transform (Buffer () AS BYTE DIM X (16) AS Long, A As Long, B As Long, C As Long, D As Long A = state (1) B = state (2) C = state (3) D = State (4) Decode 64, x, buffer FF A, B, C, D, X (0), S11,-680876936 FF D, A, B, C, X (1), S12, -389564586 FF C, D, A, B, X (2), S13, 606105819 FF B, C, D, A, X (3), S14, -1044525330 FF A, B, C, D, X (4), S11, -176418897 FF D, A, B, C, X (5), S12, 1200080426 FF C, D, A, B, X (6), S13, -1473231341 FF B, C, D, A, X (7), S14, -45705983 FF A, B, C, D, X (8), S11, 1770035416 FF D, A, B, C, X (9), S12, -1958414417 FF C, D, A, B, X (10), S13, -42063 FF B, C, D, A, X (11), S14, -1990404162 FF A, B, C, D, X (12), S11, 1804603682 FF D, A, B, C, X (13), S12, -40341101 FF C, D, A, B, X (14), S13, -1502002290 FF B, C, D, A, X (15), S14, 1236535329 GG A, B, C, D, X (1), S21, -165796510 GG D, A, B, C, X (6), S22, -1069501632 GG C, D, A, B, X (11), S23, 643717713 GG B, C, D, A, X (0), S24,-373897302 GG A, B, C, D, X (5), S21, -701558691 GG D, A, B, C, X (10), S22, 38016083 GG C, D, A, B, X (15), S23,-660478335 GG B, C, D, A, X (4), S24, -405537848 GG A, B, C, D, X (9), S21, 568446438 GG D, A, B, C, X (14), S22, -1019803690 GG C, D, A, B, X (3), S23, -187363961 GG B, C, D, A, X (8), S24, 1163531501 GG A, B, C, D, X (13), S21, -1444681467 GG D, A, B, C, X (2), S22, -51403784 GG C, D, A, B, X (7), S23, 1735328473 GG B, C, D, A, X (12), S24, -1926607734HH A, B, C, D, X (5), S31,-378558 HH D, A, B, C, X (8), S32, -2022574463 HH C, D, A, B, X (11), S33, 1839030562 HH B, C, D, A, X (14), S34, -35309556 HH A, B, C, D, X (1), S31, -1530992060 HH D, A, B, C, X (4), S32, 1272893353 HH C, D, A, B, X (7), S33,-155497632 HH B, C, D, A, X (10), S34, -1094730640 HH A, B, C, D, X (13), S31, 681279174 HH D, A, B, C, X (0), S32, -358537222 HH C, D, A, B, X (3), S33, -722521979 HH B, C, D, A, X (6), S34, 76029189 HH A, B, C, D, X (9), S31,-640364487 HH D, A, B, C, X (12), S32, -421815835 HH C, D, A, B, X (15), S33, 530742520 HH B, C, D, A, X (2), S34, -995338651 II A, B, C, D, X (0), S41, -198630844 II D, A, B, C, X (7), S42, 1126891415 II C, D, A, B, X (14), S43, -1416354905 II B, C, D, A, X (5), S44, -57434055 II A, B, C, D, X (12), S41, 1700485571 II D, A, B, C, X (3), S42, -1894986606 II C, D, A, B, X (10), S43, -1051523 II B, C, D, A, X (1), S44, -2054922799 II A, B, C, D, X (8), S41, 1873313359 II D, A, B, C, X (15), S42, -30611744 II C, D, A, B, X (6), S43, -1560198380 II B, C, D, A, X (13), S44, 1309151649 II A, B, C, D, X (4), S41, -145523070 II D, A, B, C, X (11), S42,-1120210379 II C, D, A, B, X (2), S43, 718787259 II B, C, D, A, X (9), S44, -343485551 State (1) = longoverflowadd (State (1), A) State (2) = longoverflowadd (State (2), b) State (3) = longoverflowadd (State (3), C) State (4) = longoverflowadd (State (4), D) End Sub Private sub decode (Length as integer () as long, inputbuffer () as Byte DIM INTDBLINDEX AS INTEGER, INTBYTEINDEX AS INTEGER, DBLSUM AS DOUBLE For intbyteindex = 0 to Length - 1 Step 4 dblSum = InputBuffer (intByteIndex) InputBuffer (intByteIndex 1) * 256 # InputBuffer (intByteIndex 2) * 65536 # InputBuffer (intByteIndex 3) * 16777216 # OutputBuffer (intDblIndex) = UnsignedToLong (dblSum) INTDBLINDEX = INTDBLINDEX 1 Next INTBYTEINDEX End Sub PRIVATE FUNCTION FF (A AS Long, B AS Long, X As Long, S As Long, AC As Long AS LONG A = longoverflowadd4 (a, (b and c) OR (NOT (b) and D), X, AC) A = longleftrotate (a, s) A = longoverflowadd (a, b) END FUNCTION PRIVATE FUNCTION GG (A As Long, B AS Long, X As Long, S As Long, AC As Long) AS Long A = longoverflowadd4 (a, (b And d) OR (C and not (d)), X, AC) A = longleftrotate (a, s) A = longoverflowadd (a, b) END FUNCTION PRIVATE FUNCTION HH (A As Long, B AS Long, C As Long, S As Long, AC AS Long AS Long A = longoverflowadd4 (a, b xor c xor d, x, ac) A = longleftrotate (a, s) A = longoverflowadd (a, b) END FUNCTION PRIVATE FUNCTION II (A AS Long, B AS Long, X As Long, S As Long, AC As Long) AS Long A = longoverflowadd4 (a, c xor (b or not (d)), X, AC) A = longleftrotate (a, s) A = longoverflowadd (a, b) END FUNCTION Function Longleftrotate (Value As Long, Bits as Long) As long Dim lngsign as long, LNGI As Long Bits = BITS MOD 32 IF bits = 0 Then longleftrotate = value: exit function For LNGI = 1 to Bits LNGSIGN = Value and & HC0000000 Value = (Value and & H3ffffffff) * 2 Value = value or (LNGSIGN <0) AND 1) OR (CBOOL (LNGSIGN AND & H40000000) And & H80000000) NEXT Longleftrotate = Value END FUNCTION PRIVATE FUNCTION LongoverflowAdd (Val1 As Long, Val2 As Long, LNGLOWORD AS Long, LNGOVERFLOW AS Long LNGLOWORD = (VAL1 and & HFFFF &) (Val2 and & HFFF &) LNGOVERFLOW = LNGLOWWORD / 65536 LNGHIGHWORD = ((VAL1 and & HFFFF0000) / 65536) ((Val2 and & HFFFF0000) / 65536) LNGOVERFLOW) And & HFFFF & LongoverflowAdd = unsignedtolong (LNGHighword * 65536 #) (LNGLOWWORD AND & HFFFF &)) END FUNCTION PRIVATE FUNCTION LongoverflowAdd4 (Val1 As Long, Val2 As Long, Val4 As Long AS LONG Dim Lnghighword As Long, LNGLOWORD AS Long, LNGOVERFLOW AS Long LNGLOWWORD = (VAL1 and & HFFFF &) (VAL3 and & HFFFF &) (VAL4 and & HFFFF &) LNGOVERFLOW = LNGLOWWORD / 65536 LNGHIGHWORD = ((VAL1 and & HFFFF0000) / 65536) (Val2 and & Hfff0000) / 65536) (VAL3 and & HFFF0000) / 65536) ((VAL4 AND & HFFF0000) / 65536) LNGOVERFLOW) and & HFFFF & HFFF & LongoverflowAdd4 = unsignedtolong ((LNGHIGHWORD * 65536 #) (LNGLOWWORD AND & HFFFF &)) END FUNCTION Private function unsignedtolong (Value as double) AS Long IF value <0 or value> = offset_4 Then Error 6 IF value <= maxint_4 THEN unsignedtolong = value else unsignedtolong = value - offset_4 END FUNCTION Private Function Longtounsigned (Value As Long) AS DOUBLE IF value <0 Then Longtounsigned = value offset_4 else longtounsigned = value END FUNCTION Module code end Call the MD5_String_Calc () implementation calculation in the form ------------------ VB code end -------------------------- Delphi code example: ----------------------- Md5.pas ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ -------- Unit Md5Unit; Interface Uses Cryptcon, Sysutils, Classes, Controls; Type Ulong32 = record Loword16: Word; HiWord16: Word; END; Pulong32 = ^ Ulong32; Plong = ^ longint; Hashdigest = Record A: longint; B: longint; C: longint; D: longint; End; {Hasharray} PTR_HASH = ^ hashdigest; TMD5 = Class (Tcomponent) Private {Private Declarations} FTYPE: TSOUREPE; {Source Type, WHETER ITS A File or ByteArray, OR a pASCAL STRING} FinputFilePath: String; {Full Path to Input File} FinputArray: Pbyte; {Point to Input Array} FinputString: String; {INPUT STRING} FoutputDigest: PTR_HASH; {Output MD5 Digest} FsourceLength: longint; {INPUT Length in Bytes} FactiveBlock: Array [0..15] of longint; {The 64byte block being transformed} FA, FB, FC, FD, FAA, FBB, FCC, FDD: Longint {Fa..fdd area used during step 4, The Transform. I Made the part of the Object to cut down on time used to pass variables. FPA, FPB, FPC, FPD: Plong; {FixMe! Do we need these, or just use the '@' Operator?} {PUT IN for readability} {FF, GG, HH, II Are Used in Step 4, The Transform} Procedure FF (A, B, C, D, X: Pointer; S: Byte; AC: Longint); Procedure GG (A, B, C, D, X: Pointer; S: Byte; AC: longint); Procedure HH (A, B, C, D, X: Pointer; s: Byte; AC: longint); Procedure II (A, B, C, D, X: Pointer; s: Byte; AC: longint); protected {Protected Declarations} public {Public declarations} {Initialize IS Used in Step 3, This Fills Fa..fd with init. Values And points fpa..fpd to fa .fd} Procedure MD5_INITIALIZE; {this is where all the magic happens} procated md5_transform; Procedure MD5_FINISH; Procedure MD5_HASH_BYTES; {Procedure MD5_HASH_STRING; (Pascal Style Strings ???)} Procedure MD5_HASH_FILE; {This procedure sends the data 64bytes at a time to md5_transform} Procedure MD5_HASH; Property PINPUTARRAY: PBYTE Read FinputArray Write FinputArray; Property PoutputArray: PTR_HASH ReadputDigest Write Foutputdigest; {!! See FoutputArray} Published Property INPUTTYPE: TSOURCEPE READ fTYPE WRITE FTYPE Property InputFilePath: String Read FinputFilePath Write FinputFilePath; Property InputString: String Read FinputString Write FinputString; Property INPUTLENGTH: Longint Read FsourceLength Write FsourceLength; End; {TMD5} Procedure register; {register the component to the delphi Toolbar} Const {Constants for MD5Transform Routine.} S11 = 7; S12 = 12; S13 = 17; S14 = 22; S21 = 5; S22 = 9; S23 = 14; S24 = 20; S31 = 4; S32 = 11; S33 = 16; S34 = 23; S41 = 6; S42 = 10; S43 = 15; S44 = 21; IMPLEMENTATION Function Rol (A: longint; amount: byte): longint; assembler; ASM MOV CL, AMOUNT ROL Eax, Cl END; PROCEDURE register; {Registers the component to the tool, on the tab named 'crypto'} {Now all a delphi programer Needs to do is Drag n drop to have Blowfish encryption} Begin RegisterComponents ('Crypto', [TMD5]); END; Procedure tmd5.md5_initialize; VAR A, B, C, D: longint; Begin A: = $ 67452301; b: = $ EFCDAB89; C: = $ 98badcfe; D: = $ 10325476; Move (A, FA, 4); FPA: = @fa; Move (B, FB, 4); FPB: = @fb; Move (C, FC, 4); FPC: = @fc; Move (D, FD, 4); fpd: = @fd; End; {md5_initialize} Procedure TMD5.FF (A, B, C, D, x: Pointer; S: Byte; AC: longint); {Purpose: Round 1 of the transform. Equivalent to a = b ((A F (B, C, D) X AC) <<< S) WHERE F (B, C, D) = b and c or not (b) and d } VAR Fret: longint; Begin Fret: = ((Plong (B) ^) OR ((NOT (Plong (B) ^)) and (Plong (d) ^); Plong (a) ^: = Plong (a) ^ Fret Plong (x) ^ ac; {Now do the rotate left} Longint (a ^): = rol (longint (a ^), s); {Longint (A ^): = (longint (a ^) SHL S) or (longint (a ^) SHR (32- (s)));} INC (Plong (a) ^, plong (b) ^); End; {ff} Procedure TMD5.GG (A, B, C, D, X: Pointer; S: Byte; AC: longint); {Purpose: Round 2 of the transform. Equivalent to a = b ((A G (B, C, D) X AC) <<< S) WHERE G (B, C, D) = b And D or C Not d } VAR Gret: longint; Begin Gret: = (Plong (b) ^ and plong (d) ^) or (Plong (c) ^ and (not plong (d) ^); Plong (a) ^: = Plong (a) ^ Gret Plong (x) ^ AC; Longint (a ^): = rol (longint (a ^), s); {Longint (A ^): = (longint (a ^) SHL S) or (longint (a ^) SHR (32- (s)));} INC (Plong (a) ^, plong (b) ^); End; {gg} Procedure TMD5.HH (A, B, C, D, X: Pointer; s: Byte; AC: longint); {Purpose: Round 3 of the transform. Equivalent to a = b ((A H (B, C, D) X AC) <<< s) WHERE H (B, C, D) = b xor c xor d } VAR Hret: longint; Begin Hret: = plong (b) ^ xor plong (c) ^ xor plong (d) ^; Plong (a) ^: = Plong (a) ^ hret plong (x) ^ ac; Longint (a ^): = rol (longint (a ^), s); {Longint (A ^): = (longint (a ^) SHL S) or (longint (a ^) SHR (32- (s)));} Plong (a) ^: = plong (b) ^ plong (a) ^; End; {hh} Procedure TMD5.II (A, B, C, D, x: Pointer; s: byte; ac: longint); {purpose: Round 4 of the transform. Equivalent to a = b ((A I (B, C, D) X AC) <<< S) WHERE I (B, C, D) = c xor (b or not (d)) } VAR IRET: longint; Begin IRET: = (Plong (c) ^ ^ (Plong (b) ^ or (Not Plong (D) ^))))) Plong (a) ^: = Plong (a) ^ IRET PLONG (X) ^ AC; Longint (A ^): = rol (Plong (a) ^, s); {Longint (A ^): = (longint (a ^) SHL S) or (longint (a ^) SHR (32- (s)));} Plong (a) ^: = plong (b) ^ plong (a) ^; End; {II} Procedure TMD5.MD5_TRANSFORM; {Purpose: Perform Step 4 of the algorithm. This is where all the importantant Stuff happens. this Performs The Rounds on a 64byte block. this Procedure Should Be Called In a Loop Until All Input Data Has Been Transformed. } Begin FAA: = FA; FBB: = FB; FCC: = Fc; FDD: = fd; {ROUND 1} FF (FPA, FPB, FPC, FPD, @FACTIVEBLOCK [0], S11, $ D76AA478); {1} FF (FPD, FPA, FPB, FPC, @FACTIVEBLOCK [1], S12, $ E8C7B756); {2} FF (FPC, FPD, FPA, FPB, @FACTIVEBLOCK [2], S13, $ 242070db); {3} FF (FPB, FPC, FPD, FPA, @FACTIVEBLOCK [3], S14, $ C1BDCEEE); {4} FF (FPA, FPB, FPC, FPD, @FACTIVEBLOCK [4], S11, $ F57C0FAF); {5} FF (FPD, FPA, FPB, FPC, @FACTIVEBLOCK [5], S12, $ 4787C62A); {6} FF (FPC, FPD, FPA, FPB, @FACTIVEBLOCK [6], S13, $ A8304613); {7} FF (FPB, FPC, FPD, FPA, @FACTIVEBLOCK [7], S14, $ FD469501); {8} FF (FPA, FPB, FPC, FPD, @FACTIVEBLOCK [8], S11, $ 698098D8); {9} FF (FPD, FPA, FPB, FPC, @FACTIVEBLOCK [9], S12, $ 8B44F7AF); {10} FF (FPC, FPD, FPA, FPB, @FACTIVEBLOCK [10], S13, $ FFFF5BB1); {11} FF (FPB, FPC, FPD, FPA, @FACTIVEBLOCK [11], S14, $ 895CD7BE); {12} FF (FPA, FPB, FPC, FPD, @FACTIVEBLOCK [12], S11, $ 6b901122); {13} FF (FPD, FPA, FPB, FPC, @FACTIVEBLOCK [13], S12, $ FD987193); {14} FF (FPC, FPD, FPA, FPB, @FACTIVEBLOCK [14], S13, $ A679438E); {15} FF (FPB, FPC, FPD, FPA, @FACTIVEBLOCK [15], S14, $ 49B40821); {16} {ROUND 2} GG (FPA, FPB, FPC, FPD, @FACTIVEBLOCK [1], S21, $ F61E2562); {17} GG (FPD, FPA, FPB, FPC, @FACTIVEBLOCK [6], S22, $ C040B340); {18} GG (FPC, FPD, FPA, FPB, @FACTIVEBLOCK [11], S23, $ 265E5A51); {19} GG (FPB, FPC, FPD, FPA, @FACTIVEBLOCK [0], S24, $ E9B6C7AA); {20} GG (FPA, FPB, FPC, FPD, @FACTIVEBLOCK [5], S21, $ D62F105D); {21} GG (FPD, FPA, FPB, FPC, @FACTIVEBLOCK [10], S22, $ 2441453); {22} GG (FPC, FPD, FPA, FPB, @FACTIVEBLOCK [15], S23, $ D8A1E681); {23} GG (FPB, FPC, FPD, FPA, @FACTIVEBLOCK [4], S24, $ E7D3FBC8); {24} GG (FPA, FPB, FPC, FPD, @FACTIVEBLOCK [9], S21, $ 21e1cde6); {25} GG (FPD, FPA, FPB, FPC, @FACTIVEBLOCK [14], S22, $ C33707D6); {26} GG (FPC, FPD, FPA, FPB, @FACTIVEBLOCK [3], S23, $ F4D50D87); {27} GG (FPB, FPC, FPD, FPA, @FACTIVEBLOCK [8], S24, $ 455A14ED); {28} GG (FPA, FPB, FPC, FPD, @FACTIVEBLOCK [13], S21, $ A9E3E905); {29} GG (FPD, FPA, FPB, FPC, @FACTIVEBLOCK [2], S22, $ FCEFA3F8); {30} GG (FPC, FPD, FPA, FPB, @FACTIVEBLOCK [7], S23, $ 676F02D9); {31} GG (FPB, FPC, FPD, FPA, @FACTIVEBLOCK [12], S24, $ 8D2A4C8A); {32} {ROUND 3} HH (FPA, FPB, FPC, FPD, @FACTIVEBLOCK [5], S31, $ FFFA3942); {33} HH (FPD, FPA, FPB, FPC, @FACTIVEBLOCK [8], S32, $ 8771F681); {34} HH (FPC, FPD, FPA, FPB, @FACTIVEBLOCK [11], S33, $ 6D9D6122); {35} HH (FPB, FPC, FPD, FPA, @FACTIVEBLOCK [14], S34, $ FDE5380C); {36} HH (FPA, FPB, FPC, FPD, @FACTIVEBLOCK [1], S31, $ A4BEEA44); {37} HH (FPD, FPA, FPB, FPC, @FACTIVEBLOCK [4], S32, $ 4BDECFA9); {38} HH (FPC, FPD, FPA, FPB, @FACTIVEBLOCK [7], S33, $ F6BB4B60); {39} HH (FPB, FPC, FPD, FPA, @FACTIVEBLOCK [10], S34, $ Bebfbc70); {40} HH (FPA, FPB, FPC, FPD, @FACTIVEBLOCK [13], S31, $ 289B7EC6); {41} HH (FPD, FPA, FPB, FPC, @FACTIVEBLOCK [0], S32, $ EAA127FA); {42} HH (FPC, FPD, FPA, FPB, @FACTIVEBLOCK [3], S33, $ D4EF3085); {43} HH (FPB, FPC, FPD, FPA, @FACTIVEBLOCK [6], S34, $ 4881D05); {44} HH (FPA, FPB, FPC, FPD, @FACTIVEBLOCK [9], S31, $ D9D4D039); {45} HH (FPD, FPA, FPB, FPC, @FACTIVEBLOCK [12], S32, $ E6DB99E5); {46} HH (FPC, FPD, FPA, FPB, @FACTIVEBLOCK [15], S33, $ 1FA27CF8); {47} HH (FPB, FPC, FPD, FPA, @FACTIVEBLOCK [2], S34, $ C4AC5665); {48} {Round 4} II (FPA, FPB, FPC, FPD, @FACTIVEBLOCK [0], S41, $ F4292244); {49} II (FPD, FPA, FPB, FPC, @FACTIVEBLOCK [7], S42, $ 432AFF97); {50} II (FPC, FPD, FPA, FPB, @FACTIVEBLOCK [14], S43, $ AB9423A7); {51} II (FPB, FPC, FPD, FPA, @FACTIVEBLOCK [5], S44, $ FC93A039); {52} II (FPA, FPB, FPC, FPD, @FACTIVEBLOCK [12], S41, $ 655B59C3); {53} II (FPD, FPA, FPB, FPC, @FACTIVEBLOCK [3], S42, $ 8F0CCC92); {54} II (FPC, FPD, FPA, FPB, @FACTIVEBLOCK [10], S43, $ FFEFF47D); {55} II (FPB, FPC, FPD, FPA, @FACTIVEBLOCK [1], S44, $ 85845DD1); {56} II (FPA, FPB, FPC, FPD, @FACTIVEBLOCK [8], S41, $ 6FA87E4F); {57} II (FPD, FPA, FPB, FPC, @FACTIVEBLOCK [15], S42, $ Fe2Ce6e0); {58} II (FPC, FPD, FPA, FPB, @FACTIVEBLOCK [6], S43, $ A3014314); {59} II (FPB, FPC, FPD, FPA, @FACTIVEBLOCK [13], S44, $ 4E0811A1); {60} II (FPA, FPB, FPC, FPD, @FACTIVEBLOCK [4], S41, $ F7537E82); {61} II (FPD, FPA, FPB, FPC, @FACTIVEBLOCK [11], S42, $ BD3AF235); {62} II (FPC, FPD, FPA, FPB, @FACTIVEBLOCK [2], S43, $ 2AD7D2BB); {63} II (FPB, FPC, FPD, FPA, @FACTIVEBLOCK [9], S44, $ EB86D391); {64} INC (FA, FAA); INC (FB, FBB); INC (FC, FCC); INC (FD, FDD); {ZEROIZE SENSITIVE INFORMATION} Fillchar (FactiveBlock, Sizeof (FactiveBlock), # 0); End; {TMD5.MD5_TRANSFORM} Procedure tmd5.md5_hash; VAR PSTR: PCHAR; Begin MD5_INITIALIZE; Case fType of SourceFile: Begin MD5_HASH_FILE; End; {sourcefile} SourceByteArray: Begin MD5_HASH_BYTES; End; {sourcebyteaRray} SourceString: Begin {Convert Pascal String to byte Array} PSTR: = STRALLOC (Length (FinputString) 1); Try {Protect Dyanmic Memory Allocation} Strpcopy (PSTR, FINPUTSTRING); FsourceLength: = Length (FinputString); FinputArray: = POINTER (PSTR); MD5_HASH_BYTES; Finally STRDISPOSE (PSTR); END; End; {sourceString} End; {cas} MD5_FINISH; End; {tmd5.md5_hash} Procedure TMD5.md5_hash_bytes; VAR Buffer: array [0..4159] of byte; Count64: Comp; Index: longint; Begin Move (FinputArray ^, Buffer, Fsourcelength); Count64: = fsourceLength * 8; {Save the length (in bits) Before padding} Buffer [fsourcelength]: = $ 80; {Must Always Pad with at Least A '1'} Inc (fsourceLength); While (FsourceLength Mod 64) <> 56 do begin Buffer [fsourceLength]: = 0; Inc (fsourceLength); END; Move (count64, buffer [fsourcelength], sizeof (count64) {this better be 64bits}); INDEX: = 0; INC (FSourceLength, 8); Repeat Move (Buffer [INDEX], FactiveBlock, 64); {FLIP BYTES here on mac ??} MD5_TRANSFORM; INC (INDEX, 64); Until index = fsourcelength; End; {tmd5.hash_bytes} Procedure tmd5.md5_hash_file; VAR Buffer: array [0..4159] of byte; INPUTFILE: File; Count64: Comp; DONEFILE: BOOLEAN; Index: longint; NumRead: integer; Begin DONEFILE: = FALSE; AssignFile (InputFile, FinputFilePath); Reset (InputFile, 1); Count64: = 0; Repeat Blockread (InputFile, Buffer, 4096, NumRead); Count64: = count64 Numread; IF NumRead <> 4096 {reached end of file} Then Begin Buffer [NumRead]: = $ 80; Inc (NumRead); While (Numread MOD 64) <> 56 Do Begin Buffer [NumRead]: = 0; Inc (NumRead); END; Count64: = count64 * 8; Move (count64, buffer [numread], 8); INC (Numread, 8); DONEFILE: = TRUE; END; INDEX: = 0; Repeat Move (Buffer [INDEX], FactiveBlock, 64); {Flip Bytes Here on a Mac (I thisk)} MD5_TRANSFORM; INC (INDEX, 64); Until index = Numread; Until Donefile; Closefile (InputFile); End; {TMD5.MD5_HASH_FILE} Procedure tmd5.md5_finish; Begin Foutputdigest ^ .a: = longint (fpa ^); FoutPutdigest ^ .b: = longint (fpb ^); Foutputdigest ^ .c: = longint (fpc ^); FoutPutdigest ^ .d: = longint (fpd ^); END; End. ------------------------ Delphi code end ---------------------- - Conclusion: A large piece of the ocean sprinkled, but I found a lot of information to write it, probably as the Computer Assign in our school. ^ _ ^ Thank you for your patience, finally give everyone a question, you can try your luck, "51E5D4BD3323A02CCCCDD0472AE2DC20B" This group is the result of encrypting a set of strings by MD5 algorithm Everyone guess what is my encrypted initial string? Prompt - the original string plus a total of 20 in space.