SMS4-introduksjon:
Denne algoritmen er en grupperingsalgoritme. Algoritmen har en pakkelengde på 128 biter og en nøkkellengde på 128 biter, som er 16 byte. Både krypteringsalgoritmen og nøkkelutvidelsesalgoritmen benytter en 32-runders ikke-lineær iterasjonsstruktur. Dekrypteringsalgoritmen har samme struktur som krypteringsalgoritmen, bortsett fra at rekkefølgen på rundnøkkelen er reversert, og dekrypteringshjulnøkkelen er den omvendte rekkefølgen av krypteringshjulnøkkelen. I alle basisklassene i SMS4 vil du se at grunnfunksjonene kryptering og dekryptering er de samme, men en int-type flaggbit er nødvendig for å avgjøre om den er kryptert eller dekryptert.
Grunnleggende SMS4-krypteringsalgoritme:
offentlig klasse SMS4 {
privat statisk endelig int ENCRYPT = 1; privat statisk endelig int DECRYPT = 0; offentlig statisk finale INT RUNDE = 32; privat statisk siste int BLOKK = 16;
privat byte[] Sbox = { (byte) 0xd6, (byte) 0x90, (byte) 0xe9, (byte) 0xfe, (byte) 0xcc, (byte) 0xe1, 0x3d, (byte) 0xb7, 0x16, (byte) 0xb6, 0x14, (byte) 0xc2, 0x28, (byte) 0xfb, 0x2c, 0x05, 0x2b, 0x67, (byte) 0x9a, 0x76, 0x2a, (byte) 0xbe, 0x04, (byte) 0xc3, (byte) 0xaa, 0x44, 0x13, 0x26, 0x49, (byte) 0x86, 0x06, (byte) 0x99, (byte) 0x9c, 0x42, 0x50, (byte) 0xf4, (byte) 0x91, (byte) 0xef, (byte) 0x98, 0x7a, 0x33, 0x54, 0x0b, 0x43, (byte) 0xed, (byte) 0xcf, (byte) 0xac, 0x62, (byte) 0xe4, (byte) 0xb3, 0x1c, (byte) 0xa9, (byte) 0xc9, 0x08, (byte) 0xe8, (byte) 0x95, (byte) 0x80, (byte) 0xdf, (byte) 0x94, (byte) 0xfa, 0x75, (byte) 0x8f, 0x3f, (byte) 0xa6, 0x47, 0x07, (byte) 0xa7, (byte) 0xfc, (byte) 0xf3, 0x73, 0x17, (byte) 0xba, (byte) 0x83, 0x59, 0x3c, 0x19, (byte) 0xe6, (byte) 0x85, 0x4f, (byte) 0xa8, 0x68, 0x6b, (byte) 0x81, (byte) 0xb2, 0x71, 0x64, (byte) 0xda, (byte) 0x8b, (byte) 0xf8, (byte) 0xeb, 0x0f, 0x4b, 0x70, 0x56, (byte) 0x9d, 0x35, 0x1e, 0x24, 0x0e, 0x5e, 0x63, 0x58, (byte) 0xd1, (byte) 0xa2, 0x25, 0x22, 0x7c, 0x3b, 0x01, 0x21, 0x78, (byte) 0x87, (byte) 0xd4, 0x00, 0x46, 0x57, (byte) 0x9f, (byte) 0xd3, 0x27, 0x52, 0x4c, 0x36, 0x02, (byte) 0xe7, (byte) 0xa0, (byte) 0xc4, (byte) 0xc8, (byte) 0x9e, (byte) 0xea, (byte) 0xbf, (byte) 0x8a, (byte) 0xd2, 0x40, (byte) 0xc7, 0x38, (byte) 0xb5, (byte) 0xa3, (byte) 0xf7, (byte) 0xf2, (byte) 0xce, (byte) 0xf9, 0x61, 0x15, (byte) 0xa1, (byte) 0xe0, (byte) 0xae, 0x5d, (byte) 0xa4, (byte) 0x9b, 0x34, 0x1a, 0x55, (byte) 0xad, (byte) 0x93, 0x32, 0x30, (byte) 0xf5, (byte) 0x8c, (byte) 0xb1, (byte) 0xe3, 0x1d, (byte) 0xf6, (byte) 0xe2, 0x2e, (byte) 0x82, 0x66, (byte) 0xca, 0x60, (byte) 0xc0, 0x29, 0x23, (byte) 0xab, 0x0d, 0x53, 0x4e, 0x6f, (byte) 0xd5, (byte) 0xdb, 0x37, 0x45, (byte) 0xde, (byte) 0xfd, (byte) 0x8e, 0x2f, 0x03, (byte) 0xff, 0x6a, 0x72, 0x6d, 0x6c, 0x5b, 0x51, (byte) 0x8d, 0x1b, (byte) 0xaf, (byte) 0x92, (byte) 0xbb, (byte) 0xdd, (byte) 0xbc, 0x7f, 0x11, (byte) 0xd9, 0x5c, 0x41, 0x1f, 0x10, 0x5a, (byte) 0xd8, 0x0a, (byte) 0xc1, 0x31, (byte) 0x88, (byte) 0xa5, (byte) 0xcd, 0x7b, (byte) 0xbd, 0x2d, 0x74, (byte) 0xd0, 0x12, (byte) 0xb8, (byte) 0xe5, (byte) 0xb4, (byte) 0xb0, (byte) 0x89, 0x69, (byte) 0x97, 0x4a, 0x0c, (byte) 0x96, 0x77, 0x7e, 0x65, (byte) 0xb9, (byte) 0xf1, 0x09, (byte) 0xc5, 0x6e, (byte) 0xc6, (byte) 0x84, 0x18, (byte) 0xf0, 0x7d, (byte) 0xec, 0x3a, (byte) 0xdc, 0x4d, 0x20, 0x79, (byte) 0xee, 0x5f, 0x3e, (byte) 0xd7, (byte) 0xcb, 0x39, 0x48 };
privat 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 };
privat int Rotl(int x, int y) { returner 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); }
privat int L1(int B) { retur B ^ Rotl(B, 2) ^ Rotl(B, 10) ^ Rotl(B, 18) ^ Rotl(B, 24); returner B^(B<<2|B>>>30)^(B<<10|B>>>22)^(B<<18|B>>>14)^(B<<24|B>>>8); }
privat int L2(int B) { retur B ^ Rotl(B, 13) ^ Rotl(B, 23); returner 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 = ny int[4]; int[] tmp = ny int[4]; for (int i = 0; Jeg < 4; i++) { tmp[0] = Inndata[0 + 4 * i] & 0xff; tmp[1] = Inndata[1 + 4 * i] & 0xff; tmp[2] = Inndata[2 + 4 * i] & 0xff; tmp[3] = Input[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| Input[3+4*i]); } for (r = 0; r < 32; r += 4) { mid = x[1] ^ x[2] ^ x[3] ^ rk[r + 0]; mid = ByteSub(mid); x[0] = x[0] ^ L1(midt); x4
mid = x[2] ^ x[3] ^ x[0] ^ rk[r + 1]; mid = ByteSub(mid); x[1] = x[1] ^ L1(midt); x5
mid = x[3] ^ x[0] ^ x[1] ^ rk[r + 2]; mid = ByteSub(mid); x[2] = x[2] ^ L1(midt); x6
mid = x[0] ^ x[1] ^ x[2] ^ rk[r + 3]; mid = ByteSub(mid); x[3] = x[3] ^ L1(midt); x7 }
Bakside for (int j = 0; j < 16; j += 4) { Output[j] = (byte) (x[3 - j / 4] >>> 24 & 0xFF); Output[j + 1] = (byte) (x[3 - j / 4] >>> 16 & 0xFF); Output[j + 2] = (byte) (x[3 - j / 4] >>> 8 & 0xFF); Output[j + 3] = (byte) (x[3 - j / 4] & 0xFF); } }
private void SMS4KeyExt(byte[] Key, int[] rk, int CryptFlag) { Int R, Mid; int[] x = ny int[4]; int[] tmp = ny int[4]; for (int i = 0; Jeg < 4; i++) { tmp[0] = Nøkkel[0 + 4 * i] & 0xFF; tmp[1] = Nøkkel[1 + 4 * i] & 0xff; tmp[2] = Nøkkel[2 + 4 * i] & 0xff; tmp[3] = Nøkkel[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| Nøkkel[3+4*i]; } x[0] ^= 0xa3b1bac6; x[1] ^= 0x56aa3350; x[2] ^= 0x677d9197; x[3] ^= 0xb27022dc; for (r = 0; r < 32; r += 4) { mid = x[1] ^ x[2] ^ x[3] ^ CK[r + 0]; mid = ByteSub(mid); rk[r + 0] = x[0] ^= L2(midt); rk0=K4
mid = x[2] ^ x[3] ^ x[0] ^ CK[r + 1]; mid = ByteSub(mid); rk[r + 1] = x[1] ^= L2(midt); rk1=K5
mid = x[3] ^ x[0] ^ x[1] ^ CK[r + 2]; mid = ByteSub(mid); rk[r + 2] = x[2] ^= L2(midt); rk2=K6
mid = x[0] ^ x[1] ^ x[2] ^ CK[r + 3]; mid = ByteSub(mid); rk[r + 3] = x[3] ^= L2(midt); rk3=K7 }
Dekrypter rekkefølgen på hjulnøkkelen: rk31, rk30,...,rk0 hvis (CryptFlag == DEKRYPTER) { for (r = 0; r < 16; r++) { mid = rk[r]; rk[r] = rk[31 - r]; rk[31 - r] = midt; } } }
public int sms4(byte[] in, int inLen, byte[] key, byte[] out, int CryptFlag) { int-punkt = 0; int[] round_key = ny int[RUNDE]; int[] round_key={0}; SMS4KeyExt(nøkkel, round_key, CryptFlag); byte[] input = ny byte[16]; byte[] output = ny byte[16];
mens (inLen >= BLOKK) { input = Arrays.copyOfRange(i, punkt, punkt + 16); output=Arrays.copyOfRange(ut, punkt, punkt+16); SMS4Crypt (input, output, round_key); System.arraycopy (output, 0, out, point, BLOCK); inLen -= BLOKK; punkt += BLOKK; }
returner 0; }
}
Pakket eksternt grensesnitt:
Basert på denne grunnleggende klassen er hovedgrensesnittene som følger:
privat statisk byte[] encode16(byte[] plain, byte[] nøkkel); privat statisk byte[] decode16(byte[] chiffer, byte[] nøkkel); privat statisk byte[] encode32(byte[] plain, byte[] nøkkel); privat statisk byte[] decode32(byte[] chiffer, byte[] nøkkel); offentlig statisk byte[] encodeSMS4(byte[] plain, byte[] nøkkel); offentlig statisk byte[] dekodeSMS4(byte[] chiffer, byte[] nøkkel); offentlig statisk strengdekodingSMS4toString(byte[] chiffer, byte[] nøkkel);
encode16(byte[], byte[]) er et grensesnitt for kryptering for 16-bits klartekst og 16-bits nøkler; privat statisk byte[] decode16(byte[] chiffer, byte[] nøkkel): er et grensesnitt for dekryptering av 16-bits chiffertekst og 16-bits nøkkel; privat statisk byte[] encode32(byte[] plain, byte[] key): Dette er et grensesnitt som krypterer 32-bits klartekst og 16-bits nøkler. privat statisk byte[] decode32(byte[] chiffer, byte[] nøkkel): Dette er et grensesnitt for dekryptering av 32-bits chiffertekst og 16-bits nøkler. offentlig statisk byte[] encodeSMS4(byte[] plain, byte[] key): Dette er et grensesnitt som krypterer klartekst og 16-bits nøkler med et ubegrenset antall byte. offentlig statisk byte[] dekodeSMS4(byte[] chiffer, byte[] nøkkel): Dette er et grensesnitt for dekryptering av chiffertekst og 16-bits nøkler med et ubegrenset antall bytes. offentlig statisk String decodeSMS4toString(byte[] chiffer, byte[] nøkkel): Dette er et grensesnitt for å dekryptere ubegrensede bytes med chiffertekst og 16-bits nøkler. Grensesnittmetodekode:
offentlig statisk byte[] encodeSMS4(Streng klartekst, byte[] nøkkel) { hvis (klartekst == null || klartekst.likes()) { returner null; } for (int i = klartekst.getBytes().lengde % 16; Jeg < 16; i++) { klartekst += ''; }
returner SMS4.encodeSMS4(plaintext.getBytes(), nøkkel); }
/** * SMS4-kryptering med ubegrenset klartekstlengde * * @param klartekst * @param nøkkel * @return */ offentlig statisk byte[] encodeSMS4(byte[] klartekst, byte[] nøkkel) { byte[] chiffertekst = ny byte[klartekst.lengde];
int k = 0; int plainLen = klartekst.lengde; mens (k + 16 <= plainLen) { byte[] cellPlain = ny byte[16]; for (int i = 0; Jeg < 16; i++) { cellPlain= klartekst[k + i]; } byte[] cellCipher = encode16(cellPlain, key); for (int i = 0; i < cellCipher.length; i++) { ciphertext[k + i] = cellCipher; }
k += 16; }
returner chiffertekst; }
/** * SMS4-dekryptering uten begrensning på klartekstlengde * * @param chiffertekst * @param nøkkel * @return */ offentlig statisk byte[] decodeSMS4(byte[] chiffertekst, byte[] nøkkel) { byte[] klartekst = ny byte[chiffertekst.lengde];
int k = 0; int chifferLen = chiffertekst.lengde; mens (k + 16 <= chifferLen) { byte[] cellCipher = ny byte[16]; for (int i = 0; Jeg < 16; i++) { cellCipher= chiffertekst[k + i]; } byte[] cellPlain = decode16(cellCipher, key); for (int i = 0; i < cellPlain.length; i++) { klartekst[k + i] = cellPlain; }
k += 16; }
returnere klartekst; }
/** * Dekrypter for å hente klartekststrenger * @param chiffertekst * @param nøkkel * @return */ offentlig statisk String decodeSMS4toString(byte[] ciphertext, byte[] key) { byte[] klartekst = ny byte[chiffertekst.lengde]; klartekst = dekodeSMS4 (chiffertekst, nøkkel); returnere ny streng (klartekst); }
/** * Kun 16-bits klartekst er kryptert * * @param klartekst * @param nøkkel * @return */ privat statisk byte[] encode16(byte[] klartekst, byte[] nøkkel) { byte[] chiffer = ny byte[16]; SMS4 sm4 = ny SMS4(); sm4.sms4(klartekst, 16, nøkkel, chiffer, KRYPTERING);
returnere chiffer; }
/** * Kun 16-bits chiffertekst dekrypteres * * @param klartekst * @param nøkkel * @return */ privat statisk byte[] decode16(byte[] chiffertekst, byte[] nøkkel) { byte[] plain = ny byte[16]; SMS4 sm4 = ny SMS4(); sm4.sms4 (chiffertekst, 16, nøkkel, plain, DECRYPT);
returnere uten problemer; } Jeg vil ikke bare introdusere 32-bits klartekstkryptering her, som ligner veldig på metoden med kun 16-bits klartekst.
Den grunnleggende algoritmen for kryptering og dekryptering uten å begrense lengden på klarteksten er basert på dette grunnlaget ved å kryptere og dekryptere kun 16 biter. For klartekst større enn 16 biter brukes pakkekryptering her. Hvis du støter på klartekst som 30 biter som ikke kan deles med 16, er en måte å fylle det opp på å gjøre det til det er delelig med 16. I prinsippet kan bare det minste tallet deles på 16, selvfølgelig, hvis du er fornøyd, spiller det ingen rolle om du gjør det større, fordi det er avslutningssymbolet.
Pakkekryptering går ut på å kryptere hver 16-bits klartekst én gang, og deretter sette sammen den krypterte 16-bits chifferteksten til en ny chiffertekst. I dekrypteringsprosessen deles den også opp i en enkelt 16-bits del, og deretter settes flere av disse dekrypterte klartekstene sammen til ny klartekst.
Demonstrasjon av bruk:
Nøkkel byte[] nøkkel = { 0x01, 0x23, 0x45, 0x67, (byte) 0x89, (byte) 0xab, (byte) 0xcd, (byte) 0xef, (byte) 0xfe, (byte) 0xdc, (byte) 0xba, (byte) 0x98, 0x76, 0x54, 0x32, 0x10 };
String newString = Koding, hei!; Klartekst
byte[] enOut = SMS4.encodeSMS4(newString, key); hvis (enOut == null) { retur; }
System.out.println (krypteringsresultat:); printBit(enOut);
byte[] deOut = SMS4.decodeSMS4(enOut, key); System.out.println( dekrypteringsresultat (return byte[]) :); printBit(deOut);
String deOutStr = SMS4.decodeSMS4toString(enOut, key); System.out.println( Dekrypter resultatet (returner String): + deOutStr); |