SMS4 įvadas:
Šis algoritmas yra grupavimo algoritmas. Algoritmo paketo ilgis yra 128 bitai, o rakto ilgis - 128 bitai, tai yra 16 baitų. Tiek šifravimo algoritmas, tiek rakto išplėtimo algoritmas naudoja 32 raundų netiesinę iteracijos struktūrą. Iššifravimo algoritmo struktūra yra tokia pati kaip ir šifravimo algoritmo, išskyrus tai, kad apvalaus rakto naudojimo tvarka yra atvirkštinė, o iššifravimo rato raktas yra atvirkštinė šifravimo rato rakto tvarka. Visose pagrindinėse SMS4 klasėse pamatysite, kad pagrindinės šifravimo ir iššifravimo funkcijos yra vienodos, tačiau norint nustatyti, ar jis užšifruotas, ar iššifruotas, reikalingas int tipo vėliavėlės bitas.
SMS4 šifravimo algoritmo pagrindai:
viešoji klasė SMS4 {
privatus statinis galutinis int ENCRYPT = 1; privatus statinis galutinis int DECRYPT = 0; viešas statinis finalas int ROUND = 32; privatus statinis galutinis int BLOCK = 16;
privatus baitas[] Sbox = { (baitas) 0xd6, (baitas) 0x90, (baitas) 0xe9, (baitas) 0xfe, (baitas) 0xcc, (baitas) 0xe1, 0x3d, (baitas) 0xb7, 0x16, (baitas) 0xb6, 0x14, (baitas) 0xc2, 0x28, (baitas) 0xfb, 0x2c, 0x05, 0x2b, 0x67, (baitas) 0x9a, 0x76, 0x2a, (baitas) 0xbe, 0x04, (baitas) 0xc3, (baitas) 0xaa, 0x44, 0x13, 0x26, 0x49, (baitas) 0x86, 0x06, (baitas) 0x99, (baitas) 0x9c, 0x42, 0x50, (baitas) 0xf4, (baitas) 0x91, (baitas) 0xef, (baitas) 0x98, 0x7a, 0x33, 0x54, 0x0b, 0x43, (baitas) 0xed, (baitas) 0xcf, (baitas) 0xac, 0x62, (baitas) 0xe4, (baitas) 0xb3, 0x1c, (baitas) 0xa9, (baitas) 0xc9, 0x08, (baitas) 0xe8, (baitas) 0x95, (baitas) 0x80, (baitas) 0xdf, (baitas) 0x94, (baitas) 0xfa, 0x75, (baitas) 0x8f, 0x3f, (baitas) 0xa6, 0x47, 0x07, (baitas) 0xa7, (baitas) 0xfc, (baitas) 0xf3, 0x73, 0x17, (baitas) 0xba, (baitas) 0x83, 0x59, 0x3c, 0x19, (baitas) 0xe6, (baitas) 0x85, 0x4f, (baitas) 0xa8, 0x68, 0x6b, (baitas) 0x81, (baitas) 0xb2, 0x71, 0x64, (baitas) 0xda, (baitas) 0x8b, (baitas) 0xf8, (baitas) 0xeb, 0x0f, 0x4b, 0x70, 0x56, (baitas) 0x9d, 0x35, 0x1e, 0x24, 0x0e, 0x5e, 0x63, 0x58, (baitas) 0xd1, (baitas) 0xa2, 0x25, 0x22, 0x7c, 0x3b, 0x01, 0x21, 0x78, (baitas) 0x87, (baitas) 0xd4, 0x00, 0x46, 0x57, (baitas) 0x9f, (baitas) 0xd3, 0x27, 0x52, 0x4c, 0x36, 0x02, (baitas) 0xe7, (baitas) 0xa0, (baitas) 0xc4, (baitas) 0xc8, (baitas) 0x9e, (baitas) 0xea, (baitas) 0xbf, (baitas) 0x8a, (baitas) 0xd2, 0x40, (baitas) 0xc7, 0x38, (baitas) 0xb5, (baitas) 0xa3, (baitas) 0xf7, (baitas) 0xf2, (baitas) 0xce, (baitas) 0xf9, 0x61, 0x15, (baitas) 0xa1, (baitas) 0xe0, (baitas) 0xae, 0x5d, (baitas) 0xa4, (baitas) 0x9b, 0x34, 0x1a, 0x55, (baitas) 0xad, (baitas) 0x93, 0x32, 0x30, (baitas) 0xf5, (baitas) 0x8c, (baitas) 0xb1, (baitas) 0xe3, 0x1d, (baitas) 0xf6, (baitas) 0xe2, 0x2e, (baitas) 0x82, 0x66, (baitas) 0xca, 0x60, (baitas) 0xc0, 0x29, 0x23, (baitas) 0xab, 0x0d, 0x53, 0x4e, 0x6f, (baitas) 0xd5, (baitas) 0xdb, 0x37, 0x45, (baitas) 0xde, (baitas) 0xfd, (baitas) 0x8e, 0x2f, 0x03, (baitas) 0xff, 0x6a, 0x72, 0x6d, 0x6c, 0x5b, 0x51, (baitas) 0x8d, 0x1b, (baitas) 0xaf, (baitas) 0x92, (baitas) 0xbb, (baitas) 0xdd, (baitas) 0xbc, 0x7f, 0x11, (baitas) 0xd9, 0x5c, 0x41, 0x1f, 0x10, 0x5a, (baitas) 0xd8, 0x0a, (baitas) 0xc1, 0x31, (baitas) 0x88, (baitas) 0xa5, (baitas) 0xcd, 0x7b, (baitas) 0xbd, 0x2d, 0x74, (baitas) 0xd0, 0x12, (baitas) 0xb8, (baitas) 0xe5, (baitas) 0xb4, (baitas) 0xb0, (baitas) 0x89, 0x69, (baitas) 0x97, 0x4a, 0x0c, (baitas) 0x96, 0x77, 0x7e, 0x65, (baitas) 0xb9, (baitas) 0xf1, 0x09, (baitas) 0xc5, 0x6e, (baitas) 0xc6, (baitas) 0x84, 0x18, (baitas) 0xf0, 0x7d, (baitas) 0xec, 0x3a, (baitas) 0xdc, 0x4d, 0x20, 0x79, (baitas) 0xee, 0x5f, 0x3e, (baitas) 0xd7, (baitas) 0xcb, 0x39, 0x48 };
privatus int[] CK = { 0x00070e15, 0x1c232a31, 0x383f464d, 0x545b6269, 0x70777e85, 0x8c939aa1, 0xa8afb6bd, 0xc4cbd2d9, 0xe0e7eef5, 0xfc030a11, 0x181f262d, 0x343b4249, 0x50575e65, 0x6c737a81, 0x888f969d, 0xa4abb2b9, 0xc0c7ced5, 0xdce3eaf1, 0xf8ff060d, 0x141b2229, 0x30373e45, 0x4c535a61, 0x686f767d, 0x848b9299, 0xa0a7aeb5, 0xbcc3cad1, 0xd8dfe6ed, 0xf4fb0209, 0x10171e25, 0x2c333a41, 0x484f565d, 0x646b7279 };
privatus int Rotl(int x, int y) { grąža x << y | x >>> (32 - y); }
privatus int ByteSub(int A) { return (Sbox[A >>> 24 & 0xFF] & 0xFF) << 24 | (Sbox[A >>> 16 & 0xFF] & 0xFF) << 16 | (Sbox[A >>> 8 & 0xFF] & 0xFF) << 8 | (Sbox[A & 0xFF] & 0xFF); }
privatus int L1 (int B) { return B ^ Rotl(B, 2) ^ Rotl(B, 10) ^ Rotl(B, 18) ^ Rotl(B, 24); grąžinti B^(B<<2|B>>>30)^(B<<10|B>>>22)^(B<<18|B>>>14)^(B<<24|B>>>8); }
privatus int L2 (int B) { return B ^ Rotl(B, 13) ^ Rotl(B, 23); grąžinti B^(B<<13|B>>>19)^(B<<23|B>>>9); }
void SMS4Crypt(byte[] Input, byte[] Output, int[] rk) { int r, vidutinis, x0, x1, x2, x3; int[] x = naujas int[4]; int[] tmp = naujas int[4]; for (int i = 0; I < 4; i++) { tmp[0] = Įvestis[0 + 4 * i] & 0xff; tmp[1] = Įvestis[1 + 4 * i] & 0xff; tmp[2] = Įvestis[2 + 4 * i] & 0xff; tmp[3] = Įvestis[3 + 4 * i] & 0xff; x= TMP[0] << 24 | TMP[1] << 16 | TMP[2] << 8 | TMP[3]; x=(Įvestis[0+4*i]<<24| Įvestis[1+4*i]<<16| Įvestis[2+4*i]<<8| Įvestis[3+4*i]); } už (r = 0; R < 32; r += 4) { mid = x[1] ^ x[2] ^ x[3] ^ rk[r + 0]; mid = ByteSub(vidurys); x[0] = x[0] ^ L1(vidurys); x4
mid = x[2] ^ x[3] ^ x[0] ^ rk[r + 1]; mid = ByteSub(vidurys); x[1] = x[1] ^ L1(vidurys); x5
mid = x[3] ^ x[0] ^ x[1] ^ rk[r + 2]; mid = ByteSub(vidurys); x[2] = x[2] ^ L1(vidurys); x6
mid = x[0] ^ x[1] ^ x[2] ^ rk[r + 3]; mid = ByteSub(vidurys); x[3] = x[3] ^ L1(vidurys); x7 }
Atvirkštinis for (int j = 0; J < 16; j += 4) { Išvestis[j] = (baitas) (x[3 - j / 4] >>> 24 & 0xFF); Išvestis[j + 1] = (baitas) (x[3 - j / 4] >>> 16 & 0xFF); Išvestis[j + 2] = (baitas) (x[3 - j / 4] >>> 8 & 0xFF); Išvestis[j + 3] = (baitas) (x[3 - j / 4] & 0xFF); } }
privatus void SMS4KeyExt(byte[] Raktas, int[] rk, int CryptFlag) { int r, vidurys; int[] x = naujas int[4]; int[] tmp = naujas int[4]; for (int i = 0; I < 4; i++) { tmp[0] = raktas[0 + 4 * i] & 0xFF; tmp[1] = raktas[1 + 4 * i] & 0xff; tmp[2] = Raktas[2 + 4 * i] & 0xff; tmp[3] = raktas[3 + 4 * i] & 0xff; x= TMP[0] << 24 | TMP[1] << 16 | TMP[2] << 8 | TMP[3]; x=Raktas[0+4*i]<<24| Raktas[1+4*i]<<16| Raktas[2+4*i]<<8| Raktas[3+4*i]; } x[0] ^= 0xa3b1bac6; x[1] ^= 0x56aa3350; x[2] ^= 0x677d9197; x[3] ^= 0xb27022dc; už (r = 0; R < 32; r += 4) { mid = x[1] ^ x[2] ^ x[3] ^ CK[r + 0]; mid = ByteSub(vidurys); rk[r + 0] = x[0] ^= L2(vidurys); rk0=K4
mid = x[2] ^ x[3] ^ x[0] ^ CK[r + 1]; mid = ByteSub(vidurys); rk[r + 1] = x[1] ^= L2(vidurys); rk1=K5
mid = x[3] ^ x[0] ^ x[1] ^ CK[r + 2]; mid = ByteSub(vidurys); rk[r + 2] = x[2] ^= L2(vidurys); rk2=K6
mid = x[0] ^ x[1] ^ x[2] ^ CK[r + 3]; mid = ByteSub(vidurys); rk[r + 3] = x[3] ^= L2(vidurys); rk3=K7 }
Iššifruokite rato rakto tvarką: rk31, rk30,...,rk0 if (CryptFlag == DECRYPT) { už (r = 0; R < 16; r++) { mid = rk[r]; rk[r] = rk[31 - r]; rk[31 - r] = vidurys; } } }
public int sms4(byte[] in, int inLen, byte[] key, byte[] out, int CryptFlag) { int taškas = 0; int[] round_key = naujas int[ROUND]; int[] round_key={0}; SMS4KeyExt(raktas, round_key, CryptFlag); baitas[] įvestis = naujas baitas[16]; baitas[] išvestis = naujas baitas[16];
o (inLen >= BLOKAS) { input = Arrays.copyOfRange(in, taškas, taškas + 16); output=Arrays.copyOfRange(out, taškas, taškas+16); SMS4Crypt(įvestis, išvestis, round_key); System.arraycopy(išvestis, 0, out, taškas, BLOCK); inLen -= BLOKAS; taškas += BLOKAS; }
grąža 0; }
}
Supakuota išorinė sąsaja:
Remiantis šia pagrindine klase, pagrindinės sąsajos yra šios:
privatus statinis baitas[] encode16(baitas[] paprastas, baitas[] raktas); privatus statinis baitas[] decode16(baitas[] šifras, baitas[] raktas); privatus statinis baitas[] encode32(baitas[] paprastas, baitas[] raktas); privatus statinis baitas[] decode32(baitas[] šifras, baitas[] raktas); viešasis statinis baitas[] encodeSMS4(baitas[] paprastas, baitas[] raktas); viešasis statinis baitas[] decodeSMS4(baitas[] šifras, baitas[] raktas); public static String decodeSMS4toString(byte[] cipher, byte[] key);
encode16(byte[], byte[]) yra 16 bitų paprasto teksto ir 16 bitų raktų šifravimo sąsaja; privatus statinis baitas[] decode16(baitas[] šifras, baitas[] raktas): yra sąsaja, skirta iššifruoti 16 bitų šifruotą tekstą ir 16 bitų raktą; privatus statinis baitas[] encode32(baitas[] paprastas, baitas[] raktas): Tai sąsaja, užšifruojanti 32 bitų paprasto teksto ir 16 bitų raktus. privatus statinis baitas[] decode32(baitas[] šifras, baitas[] raktas): Tai sąsaja, skirta iššifruoti 32 bitų šifruotą tekstą ir 16 bitų raktus. viešasis statinis baitas[] kodasSMS4(baitas[] paprastas, baitas[] raktas): Tai sąsaja, užšifruojanti paprasto teksto ir 16 bitų raktus su neribotu baitų skaičiumi. viešasis statinis baitas[] decodeSMS4(baitas[] šifras, baitas[] raktas): Tai sąsaja, skirta šifruoti tekstą ir 16 bitų raktus su neribotu baitų skaičiumi. public static String decodeSMS4toString(byte[] cipher, byte[] key): Tai sąsaja, skirta iššifruoti neribotą šifruoto teksto baitą ir 16 bitų raktus. Sąsajos metodo kodas:
viešasis statinis baitas[] encodeSMS4(Eilutė paprastas tekstas, baitas[] raktas) { if (paprastas tekstas == null || plaintext.equals()) { grąžinti null; } for (int i = plaintext.getBytes().length % 16; I < 16; i++) { paprastas tekstas += ''; }
grąžinti SMS4.encodeSMS4(plaintext.getBytes(), raktas); }
/** * SMS4 šifravimas su neribotu paprasto teksto ilgiu * * @param paprastas tekstas * @param raktas * @return */ viešasis statinis baitas[] encodeSMS4(baitas[] paprastas tekstas, baitas[] raktas) { baitas[] šifruotas tekstas = naujas baitas[paprastas tekstas.ilgis];
int k = 0; int plainLen = paprastas tekstas.ilgis; o (k + 16 <= plainLen) { baitas[] cellPlain = naujas baitas[16]; for (int i = 0; I < 16; i++) { cellPlain= paprastas tekstas[k + i]; } baitas[] cellCipher = encode16(cellPlain, raktas); for (int i = 0; i < cellCipher.length; i++) { šifruotas tekstas[k + i] = cellCipher; }
k += 16; }
grąžinti šifruotą tekstą; }
/** * SMS4 iššifravimas be paprasto teksto ilgio apribojimų * * @param šifruotas tekstas * @param raktas * @return */ viešasis statinis baitas[] decodeSMS4(baitas[] šifruotas tekstas, baitas[] raktas) { baitas[] paprastas tekstas = naujas baitas[šifravimo tekstas.ilgis];
int k = 0; int cipherLen = ciphertext.length; o (k + 16 <= cipherLen) { byte[] cellCipher = naujas baitas[16]; for (int i = 0; I < 16; i++) { cellCipher= šifruotas tekstas[k + i]; } baitas[] cellPlain = decode16(cellCipher, raktas); for (int i = 0; i < cellPlain.length; i++) { paprastas tekstas[k + i] = cellPlain; }
k += 16; }
grąžinti paprastą tekstą; }
/** * Iššifruoti gauti paprasto teksto eilutes * @param šifruotas tekstas * @param raktas * @return */ public static String decodeSMS4toString(byte[] ciphertext, byte[] key) { baitas[] paprastas tekstas = naujas baitas[šifravimo tekstas.ilgis]; paprastas tekstas = decodeSMS4(šifruotas tekstas, raktas); grąžinti naują eilutę (paprastas tekstas); }
/** * Užšifruojamas tik 16 bitų paprastas tekstas * * @param paprastas tekstas * @param raktas * @return */ privatus statinis baitas[] encode16(baitas[] paprastas tekstas, baitas[] raktas) { baitas[] šifras = naujas baitas[16]; SMS4 sm4 = naujas SMS4(); sm4.sms4(paprastas tekstas, 16, raktas, šifras, ENCRYPT);
grąžinti šifrą; }
/** * Iššifruojamas tik 16 bitų šifruotas tekstas * * @param paprastas tekstas * @param raktas * @return */ privatus statinis baitas[] decode16(baitas[] šifruotas tekstas, baitas[] raktas) { baitas[] paprastas = naujas baitas[16]; SMS4 sm4 = naujas SMS4(); sm4.sms4(šifruotas tekstas, 16, raktas, paprastas, IŠŠIFRUOTI);
grįžti paprastai; } Čia nepristatysiu tik 32 bitų paprasto teksto šifravimo, kuris yra labai panašus į tik 16 bitų paprasto teksto metodą.
Pagrindinis šifravimo ir iššifravimo algoritmas, neribojant paprasto teksto ilgio, pagrįstas tik 16 bitų šifravimu ir iššifravimu. Paprastam tekstui, didesniam nei 16 bitų, čia naudojamas paketų šifravimas. Jei susiduriate su paprastu tekstu, pavyzdžiui, 30 bitų, kurių negalima dalyti iš 16, būdas jį užpildyti yra sudaryti tol, kol jis bus dalijamas iš 16. Iš esmės tik mažiausią skaičių galima padalyti iš 16, žinoma, jei esate laimingas, nesvarbu, ar padidinsite, nes tai yra uždarymo simbolis.
Paketų šifravimas yra užšifruoti kiekvieną 16 bitų paprastą tekstą vieną kartą, o tada iš naujo surinkti užšifruotą 16 bitų šifruotą tekstą į naują šifruotą tekstą. Iššifravimo metu jis taip pat padalijamas į vieną 16 bitų dalį, o tada keli iš šių iššifruotų paprasto teksto vėl surenkami į naują paprastą tekstą.
Naudojimo demonstravimas:
raktas baitas[] raktas = { 0x01, 0x23, 0x45, 0x67, (baitas) 0x89, (baitas) 0xab, (baitas) 0xcd, (baitas) 0xef, (baitas) 0xfe, (baitas) 0xdc, (baitas) 0xba, (baitas) 0x98, 0x76, 0x54, 0x32, 0x10 };
Eilutė newString = Kodavimas, sveiki!; Paprastas tekstas
byte[] enOut = SMS4.encodeSMS4(newString, raktas); if (enOut == null) { grįžti; }
System.out.println(šifravimo rezultatas:); printBit(enOut);
byte[] deOut = SMS4.decodeSMS4(enOut, raktas); System.out.println( iššifravimo rezultatas (grąžinti baitą[]) :); printBit(deOut);
Eilutė deOutStr = SMS4.decodeSMS4toString(enOut, raktas); System.out.println( Iššifruoti rezultatą (grąžinti eilutę): + deOutStr); |