Uvod v SMS4:
Ta algoritem je algoritem za združevanje. Algoritem ima dolžino paketa 128 bitov in dolžino ključa 128 bitov, kar znaša 16 bajtov. Tako algoritem šifriranja kot algoritem za razširitev ključev uporabljata 32-krožno nelinearno iteracijsko strukturo. Algoritem za dešifriranje ima enako strukturo kot šifrirni algoritem, le da je vrstni red uporabe ključa kroga obrnjen, ključ kolesca za dešifriranje pa je obratni vrstni red ključa za šifrirno kolo. V vseh osnovnih razredih SMS4 boste videli, da so osnovne funkcije šifriranja in dešifriranja enake, vendar je za določitev šifriranja ali dešifriranja potrebna int-tip zastavica.
Osnove šifrirnega algoritma SMS4:
javni razred SMS4 {
zasebni statični končni int ENCRYPT = 1; zasebni statični končni int DECRYPT = 0; javni statični finale v KROGU = 32; zasebni statični končni int BLOCK = 16;
zasebni bajt[] Sbox = { (bajt) 0xd6, (bajt) 0x90, (bajt) 0xe9, (bajt) 0xfe, (bajt) 0xcc, (bajt) 0xe1, 0x3d, (bajt) 0xb7, 0x16, (bajt) 0xb6, 0x14, (bajt) 0xc2, 0x28, (bajt) 0xfb, 0x2c, 0x05, 0x2b, 0x67, (bajt) 0x9a, 0x76, 0x2a, (bajt) 0xbe, 0x04, (bajt) 0xc3, (bajt) 0xaa, 0x44, 0x13, 0x26, 0x49, (bajt) 0x86, 0x06, (bajt) 0x99, (bajt) 0x9c, 0x42, 0x50, (bajt) 0xf4, (bajt) 0x91, (bajt) 0xef, (bajt) 0x98, 0x7a, 0x33, 0x54, 0x0b, 0x43, (bajt) 0xed, (bajt) 0xcf, (bajt) 0xac, 0x62, (bajt) 0xe4, (bajt) 0xb3, 0x1c, (bajt) 0xa9, (bajt) 0xc9, 0x08, (bajt) 0xe8, (bajt) 0x95, (bajt) 0x80, (bajt) 0xdf, (bajt) 0x94, (bajt) 0xfa, 0x75, (bajt) 0x8f, 0x3f, (bajt) 0xa6, 0x47, 0x07, (bajt) 0xa7, (bajt) 0xfc, (bajt) 0xf3, 0x73, 0x17, (bajt) 0xba, (bajt) 0x83, 0x59, 0x3c, 0x19, (bajt) 0xe6, (bajt) 0x85, 0x4f, (bajt) 0xa8, 0x68, 0x6b, (bajt) 0x81, (bajt) 0xb2, 0x71, 0x64, (bajt) 0xda, (bajt) 0x8b, (bajt) 0xf8, (bajt) 0xeb, 0x0f, 0x4b, 0x70, 0x56, (bajt) 0x9d, 0x35, 0x1e, 0x24, 0x0e, 0x5e, 0x63, 0x58, (bajt) 0xd1, (bajt) 0xa2, 0x25, 0x22, 0x7c, 0x3b, 0x01, 0x21, 0x78, (bajt) 0x87, (bajt) 0xd4, 0x00, 0x46, 0x57, (bajt) 0x9f, (bajt) 0xd3, 0x27, 0x52, 0x4c, 0x36, 0x02, (bajt) 0xe7, (bajt) 0xa0, (bajt) 0xc4, (bajt) 0xc8, (bajt) 0x9e, (bajt) 0xea, (bajt) 0xbf, (bajt) 0x8a, (bajt) 0xd2, 0x40, (bajt) 0xc7, 0x38, (bajt) 0xb5, (bajt) 0xa3, (bajt) 0xf7, (bajt) 0xf2, (bajt) 0xce, (bajt) 0xf9, 0x61, 0x15, (bajt) 0xa1, (bajt) 0xe0, (bajt) 0xae, 0x5d, (bajt) 0xa4, (bajt) 0x9b, 0x34, 0x1a, 0x55, (bajt) 0xad, (bajt) 0x93, 0x32, 0x30, (bajt) 0xf5, (bajt) 0x8c, (bajt) 0xb1, (bajt) 0xe3, 0x1d, (bajt) 0xf6, (bajt) 0xe2, 0x2e, (bajt) 0x82, 0x66, (bajt) 0xca, 0x60, (bajt) 0xc0, 0x29, 0x23, (bajt) 0xab, 0x0d, 0x53, 0x4e, 0x6f, (bajt) 0xd5, (bajt) 0xdb, 0x37, 0x45, (bajt) 0xde, (bajt) 0xfd, (bajt) 0x8e, 0x2f, 0x03, (bajt) 0xff, 0x6a, 0x72, 0x6d, 0x6c, 0x5b, 0x51, (bajt) 0x8d, 0x1b, (bajt) 0xaf, (bajt) 0x92, (bajt) 0xbb, (bajt) 0xdd, (bajt) 0xbc, 0x7f, 0x11, (bajt) 0xd9, 0x5c, 0x41, 0x1f, 0x10, 0x5a, (bajt) 0xd8, 0x0a, (bajt) 0xc1, 0x31, (bajt) 0x88, (bajt) 0xa5, (bajt) 0xcd, 0x7b, (bajt) 0xbd, 0x2d, 0x74, (bajt) 0xd0, 0x12, (bajt) 0xb8, (bajt) 0xe5, (bajt) 0xb4, (bajt) 0xb0, (bajt) 0x89, 0x69, (bajt) 0x97, 0x4a, 0x0c, (bajt) 0x96, 0x77, 0x7e, 0x65, (bajt) 0xb9, (bajt) 0xf1, 0x09, (bajt) 0xc5, 0x6e, (bajt) 0xc6, (bajt) 0x84, 0x18, (bajt) 0xf0, 0x7d, (bajt) 0xec, 0x3a, (bajt) 0xdc, 0x4d, 0x20, 0x79, (bajt) 0xee, 0x5f, 0x3e, (bajt) 0xd7, (bajt) 0xcb, 0x39, 0x48 };
private 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 };
private int Rotl(int x, int y) { vrni x << y | x >>> (32 - y); }
private 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); }
private int L1(int B) { return B ^ Rotl(B, 2) ^ Rotl(B, 10) ^ Rotl(B, 18) ^ Rotl(B, 24); return B^(B<<2|B>>>30)^(B<<10|B>>>22)^(B<<18|B>>>14)^(B<<24|B>>>8); }
private int L2(int B) { return B ^ Rotl(B, 13) ^ Rotl(B, 23); return B^(B<<13|B>>>19)^(B<<23|B>>>9); }
void SMS4Crypt(byte[] Input, byte[] Output, int[] rk) { int r, mid, x0, x1, x2, x3; int[] x = nov int[4]; int[] tmp = novi int[4]; za (int i = 0; Jaz < 4; i++) { tmp[0] = Vhod[0 + 4 * i] & 0xff; tmp[1] = Vhod[1 + 4 * i] & 0xff; tmp[2] = Vhod[2 + 4 * i] & 0xff; tmp[3] = Vhod[3 + 4 * i] & 0xff; x= tmp[0] << 24 | TMP[1] << 16 | TMP[2] << 8 | TMP[3]; x=(Input[0+4*i]<<24| Input[1+4*i]<<16| Input[2+4*i]<<8| vhod[3+4*i]); } za (r = 0; r < 32; r += 4) { sredina = x[1] ^ x[2] ^ x[3] ^ rk[r + 0]; mid = ByteSub(mid); x[0] = x[0] ^ L1(sredina); x4
sredina = x[2] ^ x[3] ^ x[0] ^ rk[r + 1]; mid = ByteSub(mid); x[1] = x[1] ^ L1(sredina); x5
sredina = x[3] ^ x[0] ^ x[1] ^ rk[r + 2]; mid = ByteSub(mid); x[2] = x[2] ^ L1(sredina); x6
sredina = x[0] ^ x[1] ^ x[2] ^ rk[r + 3]; mid = ByteSub(mid); x[3] = x[3] ^ L1(sredina); x7 }
Obrat za (int j = 0; j < 16; j += 4) { Izhod[j] = (bajt) (x[3 - j / 4] >>> 24 & 0xFF); Izhod[j + 1] = (bajt) (x[3 - j / 4] >>> 16 & 0xFF); Izhod[j + 2] = (bajt) (x[3 - j / 4] >>> 8 & 0xFF); Izhod[j + 3] = (bajt) (x[3 - j / 4] & 0xFF); } }
private void SMS4KeyExt(byte[] Key, int[] rk, int CryptFlag) { int r, mid; int[] x = nov int[4]; int[] tmp = novi int[4]; za (int i = 0; Jaz < 4; i++) { tmp[0] = Ključ[0 + 4 * i] & 0xFF; tmp[1] = Ključ[1 + 4 * i] & 0xff; tmp[2] = Ključ[2 + 4 * i] & 0xff; tmp[3] = Ključ[3 + 4 * i] & 0xff; x= tmp[0] << 24 | TMP[1] << 16 | TMP[2] << 8 | TMP[3]; x=Key[0+4*i]<<24| Key[1+4*i]<<16| Key[2+4*i]<<8| Ključ[3+4*i]; } x[0] ^= 0xa3b1bac6; x[1] ^= 0x56aa3350; x[2] ^= 0x677d9197; x[3] ^= 0xb27022dc; za (r = 0; r < 32; r += 4) { sredina = x[1] ^ x[2] ^ x[3] ^ CK[r + 0]; mid = ByteSub(mid); rk[r + 0] = x[0] ^= L2(sredina); rk0=K4
sredina = x[2] ^ x[3] ^ x[0] ^ CK[r + 1]; mid = ByteSub(mid); rk[r + 1] = x[1] ^= L2(sredina); rk1=K5
sredina = x[3] ^ x[0] ^ x[1] ^ CK[r + 2]; mid = ByteSub(mid); rk[r + 2] = x[2] ^= L2(sredina); rk2=K6
sredina = x[0] ^ x[1] ^ x[2] ^ CK[r + 3]; mid = ByteSub(mid); rk[r + 3] = x[3] ^= L2(sredina); rk3=K7 }
Dešifriraj vrstni red tipke za kolo: rk31, rk30,...,rk0 if (CryptFlag == DEŠIFRIRA) { za (r = 0; r < 16; r++) { mid = rk[r]; rk[r] = rk[31 - r]; rk[31 - R] = sredina; } } }
public int sms4(byte[] in, int inLen, byte[] key, byte[] out, int CryptFlag) { int točka = 0; int[] round_key = nov int[ROUND]; int[] round_key={0}; SMS4KeyExt(key, round_key, CryptFlag); bajt[] vhod = nov bajt[16]; bajt[] output = nov bajt[16];
while (inLen >= BLOCK) { input = Arrays.copyOfRange(in, point, point + 16); output=Arrays.copyOfRange(out, point, point+16); SMS4Crypt (vhodni, izhodni, round_key); System.arraycopy(izhod, 0, izhod, točka, BLOCK); inLen -= BLOCK; točka += BLOK; }
vrni 0; }
}
Pakiran zunanji vmesnik:
Na podlagi tega osnovnega razreda so glavni vmesniki naslednji:
zasebni statični bajt[] encode16(byte[] navaden, bajt[] ključ); zasebni statični bajt[] decode16(bajt[] šifra, bajt[] ključ); zasebni statični bajt[] encode32(bajt[] navaden, bajt[] ključ); zasebni statični bajt[] decode32(bajt[] šifra, bajt[] ključ); javni statični bajt[] encodeSMS4(bajt[] navaden, bajt[] ključ); javni statični bajt[] dekodirati SMS4(bajt[] šifra, bajt[] ključ); javni statični niz dekodira SMS4toString(bajt[] šifra, bajt[] ključ);
encode16(byte[], byte[]) je vmesnik za šifriranje za 16-bitno odprto besedilo in 16-bitne ključe; zasebni statični bajt[] decode16(byte[] šifra, bajt[] ključ): je vmesnik za dešifriranje 16-bitnega šifriranega besedila in 16-bitnega ključa; zasebni statični bajt[] encode32(byte[] jasen, bajt[] ključ): To je vmesnik, ki šifrira 32-bitno odprto besedilo in 16-bitne ključe. zasebni statični bajt[] decode32(bajt[] šifra, bajt[] ključ): To je vmesnik za dešifriranje 32-bitnega šifriranega besedila in 16-bitnih ključev. public static byte[] encodeSMS4(byte[] plain, byte[] key): To je vmesnik, ki šifrira odprto besedilo in 16-bitne ključe z neomejenim številom bajtov. javni statični bajt[] dekodirati SMS4(bajt[] šifra, bajt[] ključ): To je vmesnik za dešifriranje šifriranega besedila in 16-bitnih ključev z neomejenim številom bajtov. public static String decodeSMS4toString(byte[] cipher, byte[] key): To je vmesnik za dešifriranje neomejenih bajtov šifriranega besedila in 16-bitnih ključev. Koda metode vmesnika:
javni statični bajt[] encodeSMS4(String plaintext, bajt[] ključ) { if (plaintext == null || plaintext.equals()) { return null; } for (int i = plaintext.getBytes().length % 16; Stara sem < 16; i++) { odprto besedilo += ''; }
return SMS4.encodeSMS4(plaintext.getBytes(), ključ); }
/** * Šifriranje SMS4 z neomejeno dolžino izvirnega besedila * * @param odprto besedilo * @param ključ * @return */ javni statični bajt[] encodeSMS4(byte[] navadno besedilo, bajt[] ključ) { bajt[] šifrirano besedilo = nov bajt[navadno besedilo.dolžina];
int k = 0; int plainLen = plaintext.length; medtem ko (k + 16 <= plainLen) { bajt[] cellPlain = nov bajt[16]; za (int i = 0; Stara sem < 16; i++) { cellPlain= odprto besedilo[k + i]; } bajt[] cellCipher = encode16(cellPlain, key); za (int i = 0; i < cellCipher.length; i++) { šifrirano besedilo[k + i] = cellCipher; }
k += 16; }
vrni šifrirano besedilo; }
/** * Dešifriranje SMS4 brez omejitve dolžine izvirnega besedila * * @param šifrirano besedilo * @param ključ * @return */ javni statični bajt[] dekodirati SMS4(bajt[] šifrirano besedilo, bajt[] ključ) { bajt[] odprto besedilo = nov bajt[šifrirano besedilo.dolžina];
int k = 0; int cipherLen = šifrirano besedilo.length; medtem ko (k + 16 <= cipherLen) { bajt[] cellCipher = nov bajt[16]; za (int i = 0; Stara sem < 16; i++) { cellCipher= šifrirano besedilo[k + i]; } bajt[] cellPlain = decode16(cellCipher, key); za (int i = 0; i < celicaPlain.length; i++) { plaintext[k + i] = cellPlain; }
k += 16; }
vrni izvorno besedilo; }
/** * Dešifriranje za pridobitev nizov v odprtem besedilu * @param šifrirano besedilo * @param ključ * @return */ public static String decodeSMS4toString(byte[] šifrirano besedilo, bajt[] ključ) { bajt[] odprto besedilo = nov bajt[šifrirano besedilo.dolžina]; navadno besedilo = dekodiranje SMS4(šifrirano besedilo, ključ); vrni nov String(čisto besedilo); }
/** * Šifrirano je samo 16-bitno odprto besedilo * * @param odprto besedilo * @param ključ * @return */ Zasebni statični bajt[] encode16(byte[] navadno besedilo, bajt[] ključ) { bajt[] šifra = nov bajt[16]; SMS4 sm4 = novi SMS4(); sm4.sms4 (izvirno besedilo, 16, ključ, šifra, ENCRYPT);
povratna šifra; }
/** * Dešifrirano je samo 16-bitno šifrirano besedilo * * @param odprto besedilo * @param ključ * @return */ Zasebni statični bajt[] decode16(byte[] šifrirano besedilo, bajt[] ključ) { bajt[] plain = nov bajt[16]; SMS4 sm4 = novi SMS4(); sm4.sms4 (šifrirano besedilo, 16, ključ, navadno, DEŠIFRIRANO);
Vrni se preprosto; } Tukaj ne bom predstavil le 32-bitnega šifriranja odprtega besedila, ki je zelo podobno metodi samo 16-bitnega odprtega besedila.
Osnovni algoritem za šifriranje in dešifriranje brez omejevanja dolžine odprtega besedila temelji na tej osnovi šifriranja in dešifriranja le 16 bitov. Za odprto besedilo večje od 16 bitov se tukaj uporablja šifriranje paketov. Če naletite na odprto besedilo, kot je 30 bitov, ki ga ni mogoče deliti s 16, je način, da ga zapolnite, da ga naredite do deljivosti s 16. Načeloma je mogoče le najmanjše število deliti s 16, seveda, če ste zadovoljni, ni pomembno, če ga povečate, saj je to zaključni simbol.
Šifriranje paketov pomeni, da se vsako 16-bitno besedilo enkrat šifrira, nato pa se šifrirano 16-bitno šifrirano besedilo ponovno sestavi v novo šifrirano besedilo. Med dešifriranjem se razdeli tudi na en sam 16-bitni del, nato pa se več teh dešifriranih odprtih besedil ponovno sestavi v novo odprto besedilo.
Demonstracija uporabe:
Ključ bajt[] ključ = { 0x01, 0x23, 0x45, 0x67, (bajt) 0x89, (bajt) 0xab, (bajt) 0xcd, (bajt) 0xef, (bajt) 0xfe, (bajt) 0xdc, (bajt) 0xba, (bajt) 0x98, 0x76, 0x54, 0x32, 0x10 };
String newString = Kodiranje, pozdravljen!; Navadno besedilo
bajt[] enOut = SMS4.encodeSMS4(newString, ključ); if (enOut == null) { vrnitev; }
System.out.println(rezultat šifriranja:); printBit(enOut);
bajt[] deOut = SMS4.decodeSMS4(enOut, ključ); System.out.println( rezultat dešifriranja (vrni bajt[]) :); printBit(deOut);
String deOutStr = SMS4.decodeSMS4toString(enOut, ključ); System.out.println( Dešifrirajte rezultat (vrni niz): + deOutStr); |