SMS4 Introductie:
Dit algoritme is een groeperingsalgoritme. Het algoritme heeft een pakketlengte van 128 bits en een sleutellengte van 128 bits, wat 16 bytes is. Zowel het encryptie-algoritme als het sleuteluitbreidingsalgoritme hanteren een niet-lineaire iteratiestructuur van 32 rondes. Het ontsleutelingsalgoritme heeft dezelfde structuur als het encryptie-algoritme, behalve dat de volgorde van gebruik van de ronde sleutel is omgekeerd en de sleutel van het ontsleutelwiel de omgekeerde volgorde van de sleutel van het encryptiewiel is. In alle basisklassen van SMS4 zie je dat de basisfuncties van encryptie en ontsleuteling hetzelfde zijn, maar dat er een int-type vlagbit nodig is om te bepalen of het versleuteld of versleuteld is.
Basisprincipes van het SMS4-encryptie-algoritme:
publieke klasse SMS4 {
privé statische eindint ENCRYPT = 1; privé statische eindint DECRYPT = 0; publieke statische finale INT RONDE = 32; privé statische eindint BLOCK = 16;
privé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 };
privé 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 };
privé int Rotl(int x, int y) { return x << y | x >>> (32 - y); }
private int ByteSub(int A) { terugkeer (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 = nieuwe int[4]; int[] tmp = nieuwe int[4]; voor (int i = 0; Ik < 4; i++) { tmp[0] = Input[0 + 4 * i] & 0xff; tmp[1] = Invoer[1 + 4 * i] & 0xff; tmp[2] = Invoer[2 + 4 * i] & 0xff; tmp[3] = Invoer[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]); } voor (r = 0; r < 32; r += 4) { mid = x[1] ^ x[2] ^ x[3] ^ rk[r + 0]; mid = ByteSub(mid); x[0] = x[0] ^ L1(midden); x4
mid = x[2] ^ x[3] ^ x[0] ^ rk[r + 1]; mid = ByteSub(mid); x[1] = x[1] ^ L1(midden); x5
mid = x[3] ^ x[0] ^ x[1] ^ rk[r + 2]; mid = ByteSub(mid); x[2] = x[2] ^ L1(midden); x6
mid = x[0] ^ x[1] ^ x[2] ^ rk[r + 3]; mid = ByteSub(mid); x[3] = x[3] ^ L1(midden); x7 }
Achterzijde voor (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, Midden; int[] x = nieuwe int[4]; int[] tmp = nieuwe int[4]; voor (int i = 0; Ik < 4; i++) { tmp[0] = Sleutel[0 + 4 * i] & 0xFF; tmp[1] = Sleutel[1 + 4 * i] & 0xff; tmp[2] = Sleutel[2 + 4 * i] & 0xff; tmp[3] = Sleutel[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| Key[3+4*i]; } x[0] ^= 0xa3b1bac6; x[1] ^= 0x56aa3350; x[2] ^= 0x677d9197; x[3] ^= 0xb27022dc; voor (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(midden); rk0=K4
mid = x[2] ^ x[3] ^ x[0] ^ CK[r + 1]; mid = ByteSub(mid); rk[r + 1] = x[1] ^= L2(midden); rk1=K5
mid = x[3] ^ x[0] ^ x[1] ^ CK[r + 2]; mid = ByteSub(mid); rk[r + 2] = x[2] ^= L2(midden); rk2=K6
mid = x[0] ^ x[1] ^ x[2] ^ CK[r + 3]; mid = ByteSub(mid); rk[r + 3] = x[3] ^= L2(midden); rk3=K7 }
Ontsleutel de volgorde van de wielsleutel: rk31, rk30,...,rk0 als (CryptFlag == DECRYPT) { voor (r = 0; r < 16; r++) { mid = rk[r]; rk[r] = rk[31 - r]; rk[31 - r] = midden; } } }
publieke int sms4(byte[] in, int inLen, byte[] key, byte[] out, int CryptFlag) { int punt = 0; int[] round_key = nieuwe int[RONDE]; int[] round_key={0}; SMS4KeyExt(sleutel, round_key, CryptFlag); byte[] input = nieuwe byte[16]; byte[] output = nieuwe byte[16];
terwijl (inLen >= BLOK) { input = Arrays.copyOfRange(in, punt, punt + 16); output=Arrays.copyOfRange(uit, punt, punt+16); SMS4Crypt (invoer, uitvoer, round_key); System.arraycopy (output, 0, out, point, BLOCK); inLen -= BLOK; punt += BLOK; }
return 0; }
}
Verpakte externe interface:
Op basis van deze basisklasse zijn de belangrijkste interfaces als volgt:
private statische byte[] encode16(byte[] plain, byte[] sleutel); privé statische byte[] decode16(byte[] cipher, byte[] key); private statische byte[] encode32(byte[] plain, byte[] key); private statische byte[] decode32(byte[] cipher, byte[] key); publieke statische byte[] encodeerSMS4(byte[] plain, byte[] sleutel); publieke statische byte[] decodeSMS4(byte[] cipher, byte[] key); publieke statische String decodeerSMS4toString(byte[] cipher, byte[] key);
encode16(byte[], byte[]) is een interface voor encryptie voor 16-bits platte tekst en 16-bits sleutels; Private Static Byte[] Decode16(byte[] cipher, byte[] key): is een interface voor het ontsleutelen van 16-bits ciphertext en 16-bits sleutel; Private statische byte[] encode32(byte[] plain, byte[] key): Dit is een interface die 32-bits platte tekst en 16-bits sleutels versleutelt. Private Static Byte[] Decode32(byte[] cipher, byte[] key): Dit is een interface voor het ontsleutelen van 32-bits ciphertext en 16-bits sleutels. publieke statische byte[] encodeerSMS4(byte[] plain, byte[] key): Dit is een interface die platte tekst en 16-bits sleutels versleutelt met een onbeperkt aantal bytes. publieke statische byte[] decodeSMS4(byte[] cipher, byte[] key): Dit is een interface voor het ontsleutelen van ciphertext en 16-bits sleutels met een onbeperkt aantal bytes. publieke statische String decodeSMS4toString(byte[] cipher, byte[] key): Dit is een interface voor het ontsleutelen van onbeperkte bytes aan ciphertext en 16-bits sleutels. Interfacemethodcode:
publieke statische byte[] encodeerSMS4(String plaintext, byte[] key) { als (platte tekst == null || platte tekst.gelijk aan ()) { return null; } voor (int i = plaintext.getBytes().length % 16; Ik < 16; i++) { platte tekst += ''; }
return SMS4.encodeSMS4(plaintext.getBytes(), key); }
/** * SMS4-encryptie met onbeperkte platte tekstlengte * * @param platte tekst * @param sleutel * @return */ publieke statische byte[] encodeSMS4(byte[] plaintext, byte[] key) { byte[] ciphertext = nieuwe byte[plaintext.length];
int k = 0; int plainLen = plaintext.length; terwijl (k + 16 <= plainLen) { byte[] cellPlain = nieuwe byte[16]; voor (int i = 0; Ik < 16; i++) { cellPlain= platte tekst[k + i]; } byte[] cellCipher = encode16(cellPlain, key); voor (int i = 0; i < cellCipher.length; i++) { ciphertext[k + i] = cellCipher; }
k += 16; }
Stuur ciphertext terug; }
/** * SMS4-ontsleuteling zonder limiet op de lengte van platte tekst * * @param ciphertext * @param sleutel * @return */ publieke statische byte[] decodeSMS4(byte[] ciphertext, byte[] key) { byte[] platte tekst = nieuwe byte[ciphertext.length];
int k = 0; int cipherLen = ciphertext.length; terwijl (k + 16 <= cipherLen) { byte[] cellCipher = nieuwe byte[16]; voor (int i = 0; Ik < 16; i++) { cellCipher= ciphertext[k + i]; } byte[] cellPlain = decode16(cellCipher, key); voor (int i = 0; i < cellPlain.length; i++) { plaintext[k + i] = cellPlain; }
k += 16; }
retourneren platte tekst; }
/** * Decrypt om plaintext-strings te verkrijgen * @param ciphertext * @param sleutel * @return */ publieke statische String decodeSMS4toString(byte[] ciphertext, byte[] key) { byte[] platte tekst = nieuwe byte[ciphertext.length]; platte tekst = decodeerSMS4 (ciphertext, key); geef nieuwe string (platte tekst) terug; }
/** * Alleen 16-bits platte tekst is versleuteld * * @param platte tekst * @param sleutel * @return */ private statische byte[] encode16(byte[] plaintext, byte[] key) { byte[] cipher = nieuwe byte[16]; SMS4 sm4 = nieuwe SMS4(); sm4.sms4(platte tekst, 16, sleutel, cijfer, ENCRYPT);
Return-cijfer; }
/** * Alleen 16-bits ciphertext wordt ontsleuteld * * @param platte tekst * @param sleutel * @return */ private statische byte[] decode16(byte[] ciphertext, byte[] key) { byte[] plain = nieuwe byte[16]; SMS4 sm4 = nieuwe SMS4(); sm4.sms4(ciphertext, 16, key, plain, DECRYPT);
keer eenvoudig terug; } Ik zal hier niet alleen 32-bit plaintext-encryptie introduceren, wat erg lijkt op de methode van alleen 16-bit plaintext.
Het basisalgoritme voor versleuteling en ontsleuteling zonder de lengte van de platte tekst te beperken, is gebaseerd op deze basis van het versleutelen en ontsleutelen van slechts 16 bits. Voor platte tekst groter dan 16 bits wordt hier pakketversleuteling gebruikt. Als je platte tekst tegenkomt zoals 30 bits die niet deelbaar zijn door 16, is een manier om het op te vullen door het op te vullen totdat het deelbaar is door 16. In principe kan alleen het kleinste getal door 16 worden gedeeld, natuurlijk, als je tevreden bent, maakt het niet uit of je het groter maakt, want het is het slotsymbool.
Pakketversleuteling houdt in dat elke 16-bits platte tekst één keer wordt versleuteld, en vervolgens de versleutelde 16-bits ciphertext wordt samengevoegd tot een nieuwe ciphertext. Tijdens het ontsleutelingsproces wordt het ook opgesplitst in één 16-bits stuk, waarna verschillende van deze ontsleutelde platte tekst opnieuw worden samengevoegd tot nieuwe platte tekst.
Gebruiksdemonstratie:
Sleutel byte[] key = { 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 = Code, hallo!; Platte tekst
byte[] enOut = SMS4.encodeSMS4(newString, key); als (enOut == null) { terugkeren; }
System.out.println(encryptieresultaat:); printBit(enOut);
byte[] deOut = SMS4.decodeSMS4(enOut, key); System.out.println( ontsleutelingsresultaat (return byte[]) :); printBit(deOut);
String deOutStr = SMS4.decodeSMS4toString(enOut, key); System.out.println( Decrypte het resultaat (return String): + deOutStr); |