00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028 #include <QtCrypto>
00029 #include <QCoreApplication>
00030 #include <QtDebug>
00031 #include <stdio.h>
00032
00033 QString to64 ( long v , int size )
00034 {
00035
00036
00037 QString itoa64 = "./0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
00038 QString result;
00039
00040 while ( --size >= 0 )
00041 {
00042 result.append ( itoa64.at ( ( int )( v & 0x3f ) ) );
00043 v = v >> 6;
00044 }
00045
00046 return result;
00047
00048 }
00049
00050
00051 int byte2unsigned ( int byteValue )
00052 {
00053
00054 int integerToReturn;
00055 integerToReturn = (int) byteValue & 0xff;
00056 return integerToReturn;
00057
00058 }
00059
00060 QString qca_md5crypt( const QCA::SecureArray &password, const QCA::SecureArray &salt )
00061 {
00062 QCA::SecureArray finalState, magic_string = "$1$";
00063
00064
00065 QCA::Hash hash1( "md5" );
00066 QCA::Hash hash2( "md5" );
00067
00068
00069 hash1.update ( password );
00070 hash1.update ( magic_string );
00071 hash1.update ( salt );
00072
00073
00074 hash2.update ( password );
00075 hash2.update ( salt );
00076 hash2.update ( password );
00077
00078 finalState = hash2.final();
00079
00080
00081 for ( int i = password.size() ; i > 0 ; i -= 16 )
00082 {
00083
00084 hash1.update( finalState.toByteArray().left(i > 16 ? 16 : i));
00085 }
00086
00087
00088 finalState.fill( 0 );
00089
00090 for ( int i = password.size() ; i != 0 ; i = i >> 1 )
00091 {
00092 if ( ( i & 1 ) != 0 )
00093 {
00094 hash1.update( finalState.toByteArray().left ( 1 ) );
00095 }
00096 else
00097 {
00098 hash1.update( password.toByteArray().left ( 1 ) );
00099 }
00100 }
00101
00102 finalState = hash1.final();
00103
00104
00105 for ( int i = 0 ; i < 1000 ; i++ )
00106 {
00107
00108 hash2.clear();
00109
00110 if ((i & 1) != 0)
00111 {
00112 hash2.update ( password );
00113 }
00114 else
00115 {
00116 hash2.update ( finalState.toByteArray().left( 16 ));
00117 }
00118
00119 if ((i % 3) != 0)
00120 {
00121 hash2.update ( salt );
00122 }
00123
00124 if ((i % 7) != 0)
00125 {
00126 hash2.update ( password );
00127 }
00128
00129 if ((i & 1) != 0)
00130 {
00131 hash2.update ( finalState.toByteArray().left( 16 ) );
00132 }
00133 else
00134 {
00135 hash2.update ( password );
00136 }
00137
00138 finalState = hash2.final();
00139 }
00140
00141
00142
00143 QString encodedString;
00144
00145 encodedString.append ( magic_string.toByteArray() );
00146 encodedString.append ( salt.toByteArray() );
00147 encodedString.append ( "$" );
00148
00149 long l;
00150
00151 l = ( byte2unsigned (finalState.toByteArray().at(0) ) << 16 |
00152 ( byte2unsigned (finalState.toByteArray().at(6)) ) << 8 |
00153 byte2unsigned (finalState.toByteArray().at(12)) );
00154 encodedString.append ( to64 (l, 4) );
00155
00156 l = ( byte2unsigned (finalState.toByteArray().at(1)) << 16 |
00157 ( byte2unsigned (finalState.toByteArray().at(7))) << 8 |
00158 byte2unsigned (finalState.toByteArray().at(13)) );
00159 encodedString.append ( to64 (l, 4) );
00160
00161 l = ( byte2unsigned (finalState.toByteArray().at(2)) << 16 |
00162 ( byte2unsigned (finalState.toByteArray().at(8))) << 8 |
00163 byte2unsigned (finalState.toByteArray().at(14)) );
00164 encodedString.append ( to64 (l, 4) );
00165
00166 l = ( byte2unsigned (finalState.toByteArray().at(3)) << 16 |
00167 ( byte2unsigned (finalState.toByteArray().at(9))) << 8 |
00168 byte2unsigned (finalState.toByteArray().at(15)) );
00169 encodedString.append ( to64 (l, 4) );
00170
00171 l = ( byte2unsigned (finalState.toByteArray().at(4)) << 16 |
00172 ( byte2unsigned (finalState.toByteArray().at(10))) << 8 |
00173 byte2unsigned (finalState.toByteArray().at(5)) );
00174 encodedString.append ( to64 (l, 4) );
00175
00176 l = byte2unsigned (finalState.toByteArray().at(11));
00177 encodedString.append ( to64 (l, 2) );
00178
00179 return encodedString;
00180 }
00181
00182 int main(int argc, char **argv)
00183 {
00184
00185
00186
00187 QCA::Initializer init;
00188
00189 QCA::SecureArray password, salt;
00190
00191 QCoreApplication app ( argc, argv );
00192
00193 if ( argc < 3 )
00194 {
00195 printf ( "Usage: %s password salt (salt without $1$)\n" , argv[0] );
00196 return 1;
00197 }
00198
00199 password.append( argv[1] );
00200
00201 salt.append( argv[2] );
00202
00203
00204 if( !QCA::isSupported( "md5" ) )
00205 printf ("MD5 hash not supported!\n");
00206 else
00207 {
00208 QString result = qca_md5crypt( password, salt );
00209
00210 printf ("md5crypt [ %s , %s ] = '%s'\n" , password.data(), salt.data() , qPrintable(result) );
00211
00212
00213
00214 }
00215
00216 return 0;
00217 }
00218
00219
00220
00221