├── .gitignore ├── .gitmodules ├── LyricDecoder ├── LyricDecoder │ ├── LyricDecoder.h │ ├── QQMusicDES │ │ ├── des.h │ │ └── des.c │ ├── LyricDecoder.cpp │ ├── LyricDecoder.vcxproj.filters │ └── LyricDecoder.vcxproj └── LyricDecoder.sln └── LICENSE /.gitignore: -------------------------------------------------------------------------------- 1 | # User-specific files 2 | 3 | *.user 4 | .vs/ 5 | -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "LyricDecoder/LyricDecoder/zlib"] 2 | path = LyricDecoder/LyricDecoder/zlib 3 | url = https://github.com/madler/zlib.git 4 | -------------------------------------------------------------------------------- /LyricDecoder/LyricDecoder/LyricDecoder.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | extern "C" __declspec(dllexport) char *krcdecode(char *src, int src_len); 3 | extern "C" __declspec(dllexport) char *qrcdecode(char *src, int src_len); -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2019 SuJiKiNen 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /LyricDecoder/LyricDecoder.sln: -------------------------------------------------------------------------------- 1 | 2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio 14 4 | VisualStudioVersion = 14.0.25420.1 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "LyricDecoder", "LyricDecoder\LyricDecoder.vcxproj", "{5434AE0F-54E9-4910-8521-27111B963A71}" 7 | EndProject 8 | Global 9 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 10 | Debug|x64 = Debug|x64 11 | Debug|x86 = Debug|x86 12 | Release|x64 = Release|x64 13 | Release|x86 = Release|x86 14 | EndGlobalSection 15 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 16 | {5434AE0F-54E9-4910-8521-27111B963A71}.Debug|x64.ActiveCfg = Debug|x64 17 | {5434AE0F-54E9-4910-8521-27111B963A71}.Debug|x64.Build.0 = Debug|x64 18 | {5434AE0F-54E9-4910-8521-27111B963A71}.Debug|x86.ActiveCfg = Debug|Win32 19 | {5434AE0F-54E9-4910-8521-27111B963A71}.Debug|x86.Build.0 = Debug|Win32 20 | {5434AE0F-54E9-4910-8521-27111B963A71}.Release|x64.ActiveCfg = Release|x64 21 | {5434AE0F-54E9-4910-8521-27111B963A71}.Release|x64.Build.0 = Release|x64 22 | {5434AE0F-54E9-4910-8521-27111B963A71}.Release|x86.ActiveCfg = Release|Win32 23 | {5434AE0F-54E9-4910-8521-27111B963A71}.Release|x86.Build.0 = Release|Win32 24 | EndGlobalSection 25 | GlobalSection(SolutionProperties) = preSolution 26 | HideSolutionNode = FALSE 27 | EndGlobalSection 28 | EndGlobal 29 | -------------------------------------------------------------------------------- /LyricDecoder/LyricDecoder/QQMusicDES/des.h: -------------------------------------------------------------------------------- 1 | /********************************************************************* 2 | * Filename: des.h 3 | * Author: Brad Conte (brad AT bradconte.com) 4 | * Copyright: 5 | * Disclaimer: This code is presented "as is" without any guarantees. 6 | * Details: Defines the API for the corresponding DES implementation. 7 | Note that encryption and decryption are defined by how 8 | the key setup is performed, the actual en/de-cryption is 9 | performed by the same function. 10 | *********************************************************************/ 11 | 12 | #ifndef DES_H 13 | #define DESH 14 | 15 | /*************************** HEADER FILES ***************************/ 16 | #include 17 | 18 | /****************************** MACROS ******************************/ 19 | #define DES_BLOCK_SIZE 8 // DES operates on 8 bytes at a time 20 | 21 | /**************************** DATA TYPES ****************************/ 22 | typedef unsigned char BYTE; // 8-bit byte 23 | typedef unsigned int WORD; // 32-bit word, change to "long" for 16-bit machines 24 | 25 | typedef enum { 26 | DES_ENCRYPT, 27 | DES_DECRYPT 28 | } DES_MODE; 29 | 30 | /*********************** FUNCTION DECLARATIONS **********************/ 31 | #ifdef __cplusplus 32 | extern "C" { 33 | #endif 34 | void des_key_setup(const BYTE key[], BYTE schedule[][6], DES_MODE mode); 35 | void des_crypt(const BYTE in[], BYTE out[], const BYTE key[][6]); 36 | 37 | void three_des_key_setup(const BYTE key[], BYTE schedule[][16][6], DES_MODE mode); 38 | void three_des_crypt(const BYTE in[], BYTE out[], const BYTE key[][16][6]); 39 | #ifdef __cplusplus 40 | } 41 | #endif 42 | 43 | #endif // DES_H 44 | -------------------------------------------------------------------------------- /LyricDecoder/LyricDecoder/LyricDecoder.cpp: -------------------------------------------------------------------------------- 1 | #include "LyricDecoder.h" 2 | #include "zlib/zconf.h" 3 | #include "zlib/zlib.h" 4 | #include "stdio.h" 5 | #include "QQMusicDES/des.h" 6 | #include 7 | #include 8 | #include 9 | #include 10 | 11 | #include 12 | 13 | const unsigned char key[] = { 64, 71, 97, 119, 94, 50, 116, 71, 81, 54, 49, 45, 206, 210, 110, 105 }; 14 | 15 | //unsigned char QQKey[] = "!@#)(*$%123ZXC!@!@#)(NHL"; 16 | const unsigned char QQKey[] = { 0x21, 0x40, 0x23, 0x29, 0x28, 0x2A, 0x24, 0x25, 0x31, 0x32, 0x33, 0x5A, 0x58, 0x43, 0x21, 0x40, 0x21, 0x40, 0x23, 0x29, 0x28, 0x4E, 0x48, 0x4C }; 17 | 18 | 19 | // Deflate from the src buffer. The returned memory is allocated using malloc, and the caller is responsible for freeing it. 20 | // A trailing '\0' is added to the decompress result 21 | // Returns NULL on failure. 22 | unsigned char* deflate_memory(Bytef* src, unsigned src_len) { 23 | int ret = Z_STREAM_ERROR; 24 | z_stream strm; 25 | size_t dest_len = 262144; // 256k chunk size as suggested by zlib doc 26 | Bytef* dest = (Bytef*)malloc(dest_len); 27 | if (!dest) return NULL; 28 | 29 | // allocate inflate state 30 | strm.zalloc = Z_NULL; 31 | strm.zfree = Z_NULL; 32 | strm.opaque = Z_NULL; 33 | strm.next_in = src; 34 | strm.avail_in = src_len; 35 | strm.next_out = dest; 36 | strm.avail_out = dest_len; 37 | if (inflateInit(&strm) != Z_OK) { 38 | free(dest); 39 | return NULL; 40 | } 41 | for (;;) { 42 | if (!strm.avail_in) 43 | break; 44 | ret = inflate(&strm, Z_NO_FLUSH); 45 | assert(ret != Z_STREAM_ERROR); // state not clobbered 46 | switch (ret) { 47 | case Z_NEED_DICT: 48 | case Z_DATA_ERROR: 49 | case Z_MEM_ERROR: 50 | inflateEnd(&strm); 51 | free(dest); 52 | return NULL; 53 | } 54 | if (strm.avail_out || ret == Z_STREAM_END) 55 | break; 56 | else { 57 | // double the size of output buffer 58 | Bytef* dest_new = (Bytef*)realloc(dest, 2 * dest_len); 59 | if (dest_new) { 60 | dest = dest_new; 61 | strm.next_out = dest + dest_len; 62 | strm.avail_out = dest_len; 63 | dest_len *= 2; 64 | } 65 | else { 66 | inflateEnd(&strm); 67 | free(dest); 68 | return NULL; 69 | } 70 | } 71 | } 72 | 73 | // clean up and return 74 | inflateEnd(&strm); 75 | if (ret != Z_STREAM_END) { 76 | free(dest); 77 | return NULL; 78 | } 79 | dest_len -= strm.avail_out; 80 | unsigned char* dest_new = (unsigned char*)realloc(dest, dest_len + 1); 81 | if (dest_new) 82 | dest = dest_new; 83 | else { 84 | free(dest); 85 | return NULL; 86 | } 87 | dest[dest_len] = 0; 88 | return dest; 89 | } 90 | 91 | char *krcdecode(char *src,int src_len){ 92 | if (src_len < 4 || memcmp(src, "krc1", 4) != 0) 93 | return nullptr; 94 | 95 | for (int i = 4; i < src_len; i++) { 96 | src[i] = src[i] ^ key[(i-4) % 16]; 97 | } 98 | 99 | return (char*)deflate_memory((Bytef*)src + 4, src_len - 4); 100 | } 101 | 102 | char *qrcdecode(char *src, int src_len) { 103 | if (src_len < 10 || memcmp(src, "[offset:0]", 10) != 0) 104 | return nullptr; 105 | 106 | BYTE schedule[3][16][6]; 107 | three_des_key_setup(QQKey, schedule, DES_DECRYPT); 108 | for (int i = 11; i < src_len; i += 8) 109 | three_des_crypt(reinterpret_cast(src) + i, reinterpret_cast(src) + i, schedule); 110 | 111 | return (char*)deflate_memory((Bytef*)src + 11, src_len - 11); 112 | } 113 | -------------------------------------------------------------------------------- /LyricDecoder/LyricDecoder/LyricDecoder.vcxproj.filters: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | {4FC737F1-C7A5-4376-A066-2A32D752A2FF} 6 | cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx 7 | 8 | 9 | {93995380-89BD-4b04-88EB-625FBE52EBFB} 10 | h;hh;hpp;hxx;hm;inl;inc;xsd 11 | 12 | 13 | {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} 14 | rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms 15 | 16 | 17 | 18 | 19 | 源文件 20 | 21 | 22 | 源文件 23 | 24 | 25 | 源文件 26 | 27 | 28 | 源文件 29 | 30 | 31 | 源文件 32 | 33 | 34 | 源文件 35 | 36 | 37 | 源文件 38 | 39 | 40 | 源文件 41 | 42 | 43 | 源文件 44 | 45 | 46 | 源文件 47 | 48 | 49 | 源文件 50 | 51 | 52 | 源文件 53 | 54 | 55 | 源文件 56 | 57 | 58 | 源文件 59 | 60 | 61 | 源文件 62 | 63 | 64 | 源文件 65 | 66 | 67 | 源文件 68 | 69 | 70 | 71 | 72 | 头文件 73 | 74 | 75 | 头文件 76 | 77 | 78 | 头文件 79 | 80 | 81 | 头文件 82 | 83 | 84 | 头文件 85 | 86 | 87 | 头文件 88 | 89 | 90 | 头文件 91 | 92 | 93 | 头文件 94 | 95 | 96 | 头文件 97 | 98 | 99 | 头文件 100 | 101 | 102 | 头文件 103 | 104 | 105 | 头文件 106 | 107 | 108 | 头文件 109 | 110 | 111 | -------------------------------------------------------------------------------- /LyricDecoder/LyricDecoder/LyricDecoder.vcxproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Debug 6 | Win32 7 | 8 | 9 | Release 10 | Win32 11 | 12 | 13 | Debug 14 | x64 15 | 16 | 17 | Release 18 | x64 19 | 20 | 21 | 22 | {5434AE0F-54E9-4910-8521-27111B963A71} 23 | Win32Proj 24 | LyricDecoder 25 | 8.1 26 | 27 | 28 | 29 | DynamicLibrary 30 | true 31 | v140 32 | Unicode 33 | 34 | 35 | DynamicLibrary 36 | false 37 | v140 38 | true 39 | Unicode 40 | 41 | 42 | DynamicLibrary 43 | true 44 | v140 45 | Unicode 46 | 47 | 48 | DynamicLibrary 49 | false 50 | v140 51 | true 52 | Unicode 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | true 74 | 75 | 76 | true 77 | 78 | 79 | false 80 | 81 | 82 | false 83 | 84 | 85 | 86 | 87 | 88 | Level3 89 | Disabled 90 | WIN32;_DEBUG;_WINDOWS;_USRDLL;LYRICDECODER_EXPORTS;%(PreprocessorDefinitions) 91 | 92 | 93 | Windows 94 | true 95 | 96 | 97 | 98 | 99 | 100 | 101 | Level3 102 | Disabled 103 | _DEBUG;_WINDOWS;_USRDLL;LYRICDECODER_EXPORTS;%(PreprocessorDefinitions) 104 | 105 | 106 | Windows 107 | true 108 | 109 | 110 | 111 | 112 | Level3 113 | 114 | 115 | MaxSpeed 116 | true 117 | true 118 | WIN32;NDEBUG;_WINDOWS;_USRDLL;LYRICDECODER_EXPORTS;%(PreprocessorDefinitions) 119 | 120 | 121 | Windows 122 | true 123 | true 124 | true 125 | 126 | 127 | 128 | 129 | Level3 130 | 131 | 132 | MaxSpeed 133 | true 134 | true 135 | NDEBUG;_WINDOWS;_USRDLL;LYRICDECODER_EXPORTS;%(PreprocessorDefinitions) 136 | 137 | 138 | Windows 139 | true 140 | true 141 | true 142 | 143 | 144 | 145 | 146 | 147 | 148 | 149 | 150 | 151 | 152 | 153 | 154 | 155 | 156 | 157 | 158 | 159 | 160 | 161 | 162 | 163 | 164 | 165 | 166 | 167 | 168 | 169 | 170 | 171 | 172 | 173 | 174 | 175 | 176 | 177 | 178 | 179 | 180 | 181 | -------------------------------------------------------------------------------- /LyricDecoder/LyricDecoder/QQMusicDES/des.c: -------------------------------------------------------------------------------- 1 | /********************************************************************* 2 | * WARNING: This implementation of DES is WRONG! 3 | * Never use this in real cryptography! 4 | *********************************************************************/ 5 | 6 | /********************************************************************* 7 | * Filename: des.c 8 | * Author: Brad Conte (brad AT radconte.com) 9 | * Modified by wangqr 10 | * Copyright: 11 | * Disclaimer: This code is presented "as is" without any guarantees. 12 | * Details: Implementation of the DES encryption algorithm used by 13 | QQ Music. 14 | *********************************************************************/ 15 | 16 | /*************************** HEADER FILES ***************************/ 17 | #include 18 | #include 19 | #include "des.h" 20 | 21 | /****************************** MACROS ******************************/ 22 | // Obtain bit "b" from the left and shift it "c" places from the right 23 | #define BITNUM(a,b,c) (((a[(b)/32*4+3-(b)%32/8] >> (7 - (b%8))) & 0x01) << (c)) 24 | #define BITNUMINTR(a,b,c) ((((a) >> (31 - (b))) & 0x00000001) << (c)) 25 | #define BITNUMINTL(a,b,c) ((((a) << (b)) & 0x80000000) >> (c)) 26 | 27 | // This macro converts a 6 bit block with the S-Box row defined as the first and last 28 | // bits to a 6 bit block with the row defined by the first two bits. 29 | #define SBOXBIT(a) (((a) & 0x20) | (((a) & 0x1f) >> 1) | (((a) & 0x01) << 4)) 30 | 31 | /**************************** VARIABLES *****************************/ 32 | static const BYTE sbox1[64] = { 33 | 14, 4, 13, 1, 2, 15, 11, 8, 3, 10, 6, 12, 5, 9, 0, 7, 34 | 0, 15, 7, 4, 14, 2, 13, 1, 10, 6, 12, 11, 9, 5, 3, 8, 35 | 4, 1, 14, 8, 13, 6, 2, 11, 15, 12, 9, 7, 3, 10, 5, 0, 36 | 15, 12, 8, 2, 4, 9, 1, 7, 5, 11, 3, 14, 10, 0, 6, 13 37 | }; 38 | static const BYTE sbox2[64] = { 39 | 15, 1, 8, 14, 6, 11, 3, 4, 9, 7, 2, 13, 12, 0, 5, 10, 40 | 3, 13, 4, 7, 15, 2, 8, 15, 12, 0, 1, 10, 6, 9, 11, 5, 41 | 0, 14, 7, 11, 10, 4, 13, 1, 5, 8, 12, 6, 9, 3, 2, 15, 42 | 13, 8, 10, 1, 3, 15, 4, 2, 11, 6, 7, 12, 0, 5, 14, 9 43 | }; 44 | static const BYTE sbox3[64] = { 45 | 10, 0, 9, 14, 6, 3, 15, 5, 1, 13, 12, 7, 11, 4, 2, 8, 46 | 13, 7, 0, 9, 3, 4, 6, 10, 2, 8, 5, 14, 12, 11, 15, 1, 47 | 13, 6, 4, 9, 8, 15, 3, 0, 11, 1, 2, 12, 5, 10, 14, 7, 48 | 1, 10, 13, 0, 6, 9, 8, 7, 4, 15, 14, 3, 11, 5, 2, 12 49 | }; 50 | static const BYTE sbox4[64] = { 51 | 7, 13, 14, 3, 0, 6, 9, 10, 1, 2, 8, 5, 11, 12, 4, 15, 52 | 13, 8, 11, 5, 6, 15, 0, 3, 4, 7, 2, 12, 1, 10, 14, 9, 53 | 10, 6, 9, 0, 12, 11, 7, 13, 15, 1, 3, 14, 5, 2, 8, 4, 54 | 3, 15, 0, 6, 10, 10, 13, 8, 9, 4, 5, 11, 12, 7, 2, 14 55 | }; 56 | static const BYTE sbox5[64] = { 57 | 2, 12, 4, 1, 7, 10, 11, 6, 8, 5, 3, 15, 13, 0, 14, 9, 58 | 14, 11, 2, 12, 4, 7, 13, 1, 5, 0, 15, 10, 3, 9, 8, 6, 59 | 4, 2, 1, 11, 10, 13, 7, 8, 15, 9, 12, 5, 6, 3, 0, 14, 60 | 11, 8, 12, 7, 1, 14, 2, 13, 6, 15, 0, 9, 10, 4, 5, 3 61 | }; 62 | static const BYTE sbox6[64] = { 63 | 12, 1, 10, 15, 9, 2, 6, 8, 0, 13, 3, 4, 14, 7, 5, 11, 64 | 10, 15, 4, 2, 7, 12, 9, 5, 6, 1, 13, 14, 0, 11, 3, 8, 65 | 9, 14, 15, 5, 2, 8, 12, 3, 7, 0, 4, 10, 1, 13, 11, 6, 66 | 4, 3, 2, 12, 9, 5, 15, 10, 11, 14, 1, 7, 6, 0, 8, 13 67 | }; 68 | static const BYTE sbox7[64] = { 69 | 4, 11, 2, 14, 15, 0, 8, 13, 3, 12, 9, 7, 5, 10, 6, 1, 70 | 13, 0, 11, 7, 4, 9, 1, 10, 14, 3, 5, 12, 2, 15, 8, 6, 71 | 1, 4, 11, 13, 12, 3, 7, 14, 10, 15, 6, 8, 0, 5, 9, 2, 72 | 6, 11, 13, 8, 1, 4, 10, 7, 9, 5, 0, 15, 14, 2, 3, 12 73 | }; 74 | static const BYTE sbox8[64] = { 75 | 13, 2, 8, 4, 6, 15, 11, 1, 10, 9, 3, 14, 5, 0, 12, 7, 76 | 1, 15, 13, 8, 10, 3, 7, 4, 12, 5, 6, 11, 0, 14, 9, 2, 77 | 7, 11, 4, 1, 9, 12, 14, 2, 0, 6, 10, 13, 15, 3, 5, 8, 78 | 2, 1, 14, 7, 4, 10, 8, 13, 15, 12, 9, 0, 3, 5, 6, 11 79 | }; 80 | 81 | /*********************** FUNCTION DEFINITIONS ***********************/ 82 | // Initial (Inv)Permutation step 83 | void IP(WORD state[], const BYTE in[]) 84 | { 85 | state[0] = BITNUM(in,57,31) | BITNUM(in,49,30) | BITNUM(in,41,29) | BITNUM(in,33,28) | 86 | BITNUM(in,25,27) | BITNUM(in,17,26) | BITNUM(in,9,25) | BITNUM(in,1,24) | 87 | BITNUM(in,59,23) | BITNUM(in,51,22) | BITNUM(in,43,21) | BITNUM(in,35,20) | 88 | BITNUM(in,27,19) | BITNUM(in,19,18) | BITNUM(in,11,17) | BITNUM(in,3,16) | 89 | BITNUM(in,61,15) | BITNUM(in,53,14) | BITNUM(in,45,13) | BITNUM(in,37,12) | 90 | BITNUM(in,29,11) | BITNUM(in,21,10) | BITNUM(in,13,9) | BITNUM(in,5,8) | 91 | BITNUM(in,63,7) | BITNUM(in,55,6) | BITNUM(in,47,5) | BITNUM(in,39,4) | 92 | BITNUM(in,31,3) | BITNUM(in,23,2) | BITNUM(in,15,1) | BITNUM(in,7,0); 93 | 94 | state[1] = BITNUM(in,56,31) | BITNUM(in,48,30) | BITNUM(in,40,29) | BITNUM(in,32,28) | 95 | BITNUM(in,24,27) | BITNUM(in,16,26) | BITNUM(in,8,25) | BITNUM(in,0,24) | 96 | BITNUM(in,58,23) | BITNUM(in,50,22) | BITNUM(in,42,21) | BITNUM(in,34,20) | 97 | BITNUM(in,26,19) | BITNUM(in,18,18) | BITNUM(in,10,17) | BITNUM(in,2,16) | 98 | BITNUM(in,60,15) | BITNUM(in,52,14) | BITNUM(in,44,13) | BITNUM(in,36,12) | 99 | BITNUM(in,28,11) | BITNUM(in,20,10) | BITNUM(in,12,9) | BITNUM(in,4,8) | 100 | BITNUM(in,62,7) | BITNUM(in,54,6) | BITNUM(in,46,5) | BITNUM(in,38,4) | 101 | BITNUM(in,30,3) | BITNUM(in,22,2) | BITNUM(in,14,1) | BITNUM(in,6,0); 102 | } 103 | 104 | void InvIP(WORD state[], BYTE in[]) 105 | { 106 | in[3] = BITNUMINTR(state[1],7,7) | BITNUMINTR(state[0],7,6) | BITNUMINTR(state[1],15,5) | 107 | BITNUMINTR(state[0],15,4) | BITNUMINTR(state[1],23,3) | BITNUMINTR(state[0],23,2) | 108 | BITNUMINTR(state[1],31,1) | BITNUMINTR(state[0],31,0); 109 | 110 | in[2] = BITNUMINTR(state[1],6,7) | BITNUMINTR(state[0],6,6) | BITNUMINTR(state[1],14,5) | 111 | BITNUMINTR(state[0],14,4) | BITNUMINTR(state[1],22,3) | BITNUMINTR(state[0],22,2) | 112 | BITNUMINTR(state[1],30,1) | BITNUMINTR(state[0],30,0); 113 | 114 | in[1] = BITNUMINTR(state[1],5,7) | BITNUMINTR(state[0],5,6) | BITNUMINTR(state[1],13,5) | 115 | BITNUMINTR(state[0],13,4) | BITNUMINTR(state[1],21,3) | BITNUMINTR(state[0],21,2) | 116 | BITNUMINTR(state[1],29,1) | BITNUMINTR(state[0],29,0); 117 | 118 | in[0] = BITNUMINTR(state[1],4,7) | BITNUMINTR(state[0],4,6) | BITNUMINTR(state[1],12,5) | 119 | BITNUMINTR(state[0],12,4) | BITNUMINTR(state[1],20,3) | BITNUMINTR(state[0],20,2) | 120 | BITNUMINTR(state[1],28,1) | BITNUMINTR(state[0],28,0); 121 | 122 | in[7] = BITNUMINTR(state[1],3,7) | BITNUMINTR(state[0],3,6) | BITNUMINTR(state[1],11,5) | 123 | BITNUMINTR(state[0],11,4) | BITNUMINTR(state[1],19,3) | BITNUMINTR(state[0],19,2) | 124 | BITNUMINTR(state[1],27,1) | BITNUMINTR(state[0],27,0); 125 | 126 | in[6] = BITNUMINTR(state[1],2,7) | BITNUMINTR(state[0],2,6) | BITNUMINTR(state[1],10,5) | 127 | BITNUMINTR(state[0],10,4) | BITNUMINTR(state[1],18,3) | BITNUMINTR(state[0],18,2) | 128 | BITNUMINTR(state[1],26,1) | BITNUMINTR(state[0],26,0); 129 | 130 | in[5] = BITNUMINTR(state[1],1,7) | BITNUMINTR(state[0],1,6) | BITNUMINTR(state[1],9,5) | 131 | BITNUMINTR(state[0],9,4) | BITNUMINTR(state[1],17,3) | BITNUMINTR(state[0],17,2) | 132 | BITNUMINTR(state[1],25,1) | BITNUMINTR(state[0],25,0); 133 | 134 | in[4] = BITNUMINTR(state[1],0,7) | BITNUMINTR(state[0],0,6) | BITNUMINTR(state[1],8,5) | 135 | BITNUMINTR(state[0],8,4) | BITNUMINTR(state[1],16,3) | BITNUMINTR(state[0],16,2) | 136 | BITNUMINTR(state[1],24,1) | BITNUMINTR(state[0],24,0); 137 | } 138 | 139 | WORD f(WORD state, const BYTE key[]) 140 | { 141 | BYTE lrgstate[6]; //,i; 142 | WORD t1,t2; 143 | 144 | // Expantion Permutation 145 | t1 = BITNUMINTL(state,31,0) | ((state & 0xf0000000) >> 1) | BITNUMINTL(state,4,5) | 146 | BITNUMINTL(state,3,6) | ((state & 0x0f000000) >> 3) | BITNUMINTL(state,8,11) | 147 | BITNUMINTL(state,7,12) | ((state & 0x00f00000) >> 5) | BITNUMINTL(state,12,17) | 148 | BITNUMINTL(state,11,18) | ((state & 0x000f0000) >> 7) | BITNUMINTL(state,16,23); 149 | 150 | t2 = BITNUMINTL(state,15,0) | ((state & 0x0000f000) << 15) | BITNUMINTL(state,20,5) | 151 | BITNUMINTL(state,19,6) | ((state & 0x00000f00) << 13) | BITNUMINTL(state,24,11) | 152 | BITNUMINTL(state,23,12) | ((state & 0x000000f0) << 11) | BITNUMINTL(state,28,17) | 153 | BITNUMINTL(state,27,18) | ((state & 0x0000000f) << 9) | BITNUMINTL(state,0,23); 154 | 155 | lrgstate[0] = (t1 >> 24) & 0x000000ff; 156 | lrgstate[1] = (t1 >> 16) & 0x000000ff; 157 | lrgstate[2] = (t1 >> 8) & 0x000000ff; 158 | lrgstate[3] = (t2 >> 24) & 0x000000ff; 159 | lrgstate[4] = (t2 >> 16) & 0x000000ff; 160 | lrgstate[5] = (t2 >> 8) & 0x000000ff; 161 | 162 | // Key XOR 163 | lrgstate[0] ^= key[0]; 164 | lrgstate[1] ^= key[1]; 165 | lrgstate[2] ^= key[2]; 166 | lrgstate[3] ^= key[3]; 167 | lrgstate[4] ^= key[4]; 168 | lrgstate[5] ^= key[5]; 169 | 170 | // S-Box Permutation 171 | state = (sbox1[SBOXBIT(lrgstate[0] >> 2)] << 28) | 172 | (sbox2[SBOXBIT(((lrgstate[0] & 0x03) << 4) | (lrgstate[1] >> 4))] << 24) | 173 | (sbox3[SBOXBIT(((lrgstate[1] & 0x0f) << 2) | (lrgstate[2] >> 6))] << 20) | 174 | (sbox4[SBOXBIT(lrgstate[2] & 0x3f)] << 16) | 175 | (sbox5[SBOXBIT(lrgstate[3] >> 2)] << 12) | 176 | (sbox6[SBOXBIT(((lrgstate[3] & 0x03) << 4) | (lrgstate[4] >> 4))] << 8) | 177 | (sbox7[SBOXBIT(((lrgstate[4] & 0x0f) << 2) | (lrgstate[5] >> 6))] << 4) | 178 | sbox8[SBOXBIT(lrgstate[5] & 0x3f)]; 179 | 180 | // P-Box Permutation 181 | state = BITNUMINTL(state,15,0) | BITNUMINTL(state,6,1) | BITNUMINTL(state,19,2) | 182 | BITNUMINTL(state,20,3) | BITNUMINTL(state,28,4) | BITNUMINTL(state,11,5) | 183 | BITNUMINTL(state,27,6) | BITNUMINTL(state,16,7) | BITNUMINTL(state,0,8) | 184 | BITNUMINTL(state,14,9) | BITNUMINTL(state,22,10) | BITNUMINTL(state,25,11) | 185 | BITNUMINTL(state,4,12) | BITNUMINTL(state,17,13) | BITNUMINTL(state,30,14) | 186 | BITNUMINTL(state,9,15) | BITNUMINTL(state,1,16) | BITNUMINTL(state,7,17) | 187 | BITNUMINTL(state,23,18) | BITNUMINTL(state,13,19) | BITNUMINTL(state,31,20) | 188 | BITNUMINTL(state,26,21) | BITNUMINTL(state,2,22) | BITNUMINTL(state,8,23) | 189 | BITNUMINTL(state,18,24) | BITNUMINTL(state,12,25) | BITNUMINTL(state,29,26) | 190 | BITNUMINTL(state,5,27) | BITNUMINTL(state,21,28) | BITNUMINTL(state,10,29) | 191 | BITNUMINTL(state,3,30) | BITNUMINTL(state,24,31); 192 | 193 | // Return the final state value 194 | return(state); 195 | } 196 | 197 | void des_key_setup(const BYTE key[], BYTE schedule[][6], DES_MODE mode) 198 | { 199 | WORD i, j, to_gen, C, D; 200 | const WORD key_rnd_shift[16] = {1,1,2,2,2,2,2,2,1,2,2,2,2,2,2,1}; 201 | const WORD key_perm_c[28] = {56,48,40,32,24,16,8,0,57,49,41,33,25,17, 202 | 9,1,58,50,42,34,26,18,10,2,59,51,43,35}; 203 | const WORD key_perm_d[28] = {62,54,46,38,30,22,14,6,61,53,45,37,29,21, 204 | 13,5,60,52,44,36,28,20,12,4,27,19,11,3}; 205 | const WORD key_compression[48] = {13,16,10,23,0,4,2,27,14,5,20,9, 206 | 22,18,11,3,25,7,15,6,26,19,12,1, 207 | 40,51,30,36,46,54,29,39,50,44,32,47, 208 | 43,48,38,55,33,52,45,41,49,35,28,31}; 209 | 210 | // Permutated Choice #1 (copy the key in, ignoring parity bits). 211 | for (i = 0, j = 31, C = 0; i < 28; ++i, --j) 212 | C |= BITNUM(key,key_perm_c[i],j); 213 | for (i = 0, j = 31, D = 0; i < 28; ++i, --j) 214 | D |= BITNUM(key,key_perm_d[i],j); 215 | 216 | // Generate the 16 subkeys. 217 | for (i = 0; i < 16; ++i) { 218 | C = ((C << key_rnd_shift[i]) | (C >> (28-key_rnd_shift[i]))) & 0xfffffff0; 219 | D = ((D << key_rnd_shift[i]) | (D >> (28-key_rnd_shift[i]))) & 0xfffffff0; 220 | 221 | // Decryption subkeys are reverse order of encryption subkeys so 222 | // generate them in reverse if the key schedule is for decryption useage. 223 | if (mode == DES_DECRYPT) 224 | to_gen = 15 - i; 225 | else /*(if mode == DES_ENCRYPT)*/ 226 | to_gen = i; 227 | // Initialize the array 228 | for (j = 0; j < 6; ++j) 229 | schedule[to_gen][j] = 0; 230 | for (j = 0; j < 24; ++j) 231 | schedule[to_gen][j/8] |= BITNUMINTR(C,key_compression[j],7 - (j%8)); 232 | for ( ; j < 48; ++j) 233 | schedule[to_gen][j/8] |= BITNUMINTR(D,key_compression[j] - 27,7 - (j%8)); 234 | } 235 | } 236 | 237 | void des_crypt(const BYTE in[], BYTE out[], const BYTE key[][6]) 238 | { 239 | WORD state[2],idx,t; 240 | 241 | IP(state,in); 242 | 243 | for (idx=0; idx < 15; ++idx) { 244 | t = state[1]; 245 | state[1] = f(state[1],key[idx]) ^ state[0]; 246 | state[0] = t; 247 | } 248 | // Perform the final loop manually as it doesn't switch sides 249 | state[0] = f(state[1],key[15]) ^ state[0]; 250 | 251 | InvIP(state,out); 252 | } 253 | 254 | void three_des_key_setup(const BYTE key[], BYTE schedule[][16][6], DES_MODE mode) 255 | { 256 | if (mode == DES_ENCRYPT) { 257 | des_key_setup(&key[0],schedule[0],mode); 258 | des_key_setup(&key[8],schedule[1],!mode); 259 | des_key_setup(&key[16],schedule[2],mode); 260 | } 261 | else /*if (mode == DES_DECRYPT*/ { 262 | des_key_setup(&key[16],schedule[0],mode); 263 | des_key_setup(&key[8],schedule[1],!mode); 264 | des_key_setup(&key[0],schedule[2],mode); 265 | } 266 | } 267 | 268 | void three_des_crypt(const BYTE in[], BYTE out[], const BYTE key[][16][6]) 269 | { 270 | des_crypt(in,out,key[0]); 271 | des_crypt(out,out,key[1]); 272 | des_crypt(out,out,key[2]); 273 | } 274 | --------------------------------------------------------------------------------