Ця стаття є дзеркальною статтею машинного перекладу, будь ласка, натисніть тут, щоб перейти до оригінальної статті.

Вид: 16332|Відповідь: 4

[Алгоритм] Алгоритм SMS4, який є алгоритмом симетричної блочної криптографії

[Копіювати посилання]
Опубліковано 08.12.2015 21:49:35 | | |
Це алгоритм блочної криптографії, але він використовує багато різних методів, і тепер в Інтернеті є специфічний вихідний код, але цей код все одно має певну дослідницьку цінність, якщо вас це теж цікавить, ви можете прийти, спілкуватися і навчатися разом. Насправді, немає сенсу давати вам повний код, але я все одно додаю повну адресу коду до http://www.2cto.com/kf/201501/369374.html
У ньому також є S-коробка, що дуже важливо, і використовується в алгоритмі DES, тому порада мого колеги — чітко зрозуміти S-коробку алгоритму DES, щоб я міг зрозуміти, про що йдеться специфікація в цьому алгоритмі SMS4. Специфікація не додається.





Попередній:Схоже, що це місце давно не оновлювали, і я буду оновлювати мову C щодня в майбутньому.
Наступний:Мова C, повна версія відео
Опубліковано 08.12.2015 22:19:05 |

Вступ до SMS4:

Цей алгоритм є алгоритмом групування. Алгоритм має довжину пакета 128 біт, а довжина ключа — 128 біт, що становить 16 байт. І алгоритм шифрування, і алгоритм розширення ключа використовують структуру нелінійної ітерації з 32 раундами. Алгоритм дешифрування має ту ж структуру, що й алгоритм шифрування, за винятком того, що порядок використання ключа раунду змінюється, а ключ колеса розшифрування — це зворотний порядок ключа колеса шифрування. У всіх базових класах SMS4 ви побачите, що базові функції шифрування та дешифрування однакові, але для визначення шифрування чи розшифрування потрібен прапорецький біт типу int.

Основи алгоритму шифрування SMS4:



публічний клас SMS4 {

    приватний статичний фінальний int ENCRYPT = 1;
    приватний статичний фінальний int DECRYPT = 0;
    публічний статичний фінальний інтелект РАУНД = 32;
    приватний статичний фінальний int BLOCK = 16;

    приватний байт[] Sbox = { (байт) 0xd6, (байт) 0x90, (байт) 0xe9, (байт) 0xfe,
            (байт) 0xcc, (байт) 0xe1, 0x3d, (байт) 0xb7, 0x16, (байт) 0xb6,
            0x14, (байт) 0xc2, 0x28, (байт) 0xfb, 0x2c, 0x05, 0x2b, 0x67,
            (байт) 0x9a, 0x76, 0x2a, (байт) 0xbe, 0x04, (байт) 0xc3,
            (байт) 0xaa, 0x44, 0x13, 0x26, 0x49, (байт) 0x86, 0x06,
            (байт) 0x99, (байт) 0x9c, 0x42, 0x50, (байт) 0xf4, (байт) 0x91,
            (байт) 0xef, (байт) 0x98, 0x7a, 0x33, 0x54, 0x0b, 0x43,
            (байт) 0xed, (байт) 0xcf, (байт) 0xac, 0x62, (байт) 0xe4,
            (байт) 0xb3, 0x1c, (байт) 0xa9, (байт) 0xc9, 0x08, (байт) 0xe8,
            (байт) 0x95, (байт) 0x80, (байт) 0xdf, (байт) 0x94, (байт) 0xfa,
            0x75, (байт) 0x8f, 0x3f, (байт) 0xa6, 0x47, 0x07, (байт) 0xa7,
            (байт) 0xfc, (байт) 0xf3, 0x73, 0x17, (байт) 0xba, (байт) 0x83,
            0x59, 0x3c, 0x19, (байт) 0xe6, (байт) 0x85, 0x4f, (байт) 0xa8,
            0x68, 0x6b, (байт) 0x81, (байт) 0xb2, 0x71, 0x64, (байт) 0xda,
            (байт) 0x8b, (байт) 0xf8, (байт) 0xeb, 0x0f, 0x4b, 0x70, 0x56,
            (байт) 0x9d, 0x35, 0x1e, 0x24, 0x0e, 0x5e, 0x63, 0x58, (байт) 0xd1,
            (байт) 0xa2, 0x25, 0x22, 0x7c, 0x3b, 0x01, 0x21, 0x78, (байт) 0x87,
            (байт) 0xd4, 0x00, 0x46, 0x57, (байт) 0x9f, (байт) 0xd3, 0x27,
            0x52, 0x4c, 0x36, 0x02, (байт) 0xe7, (байт) 0xa0, (байт) 0xc4,
            (байт) 0xc8, (байт) 0x9e, (байт) 0xea, (байт) 0xbf, (байт) 0x8a,
            (байт) 0xd2, 0x40, (байт) 0xc7, 0x38, (байт) 0xb5, (байт) 0xa3,
            (байт) 0xf7, (байт) 0xf2, (байт) 0xce, (байт) 0xf9, 0x61, 0x15,
            (байт) 0xa1, (байт) 0xe0, (байт) 0xae, 0x5d, (байт) 0xa4,
            (байт) 0x9b, 0x34, 0x1a, 0x55, (байт) 0xad, (байт) 0x93, 0x32,
            0x30, (байт) 0xf5, (байт) 0x8c, (байт) 0xb1, (байт) 0xe3, 0x1d,
            (байт) 0xf6, (байт) 0xe2, 0x2e, (байт) 0x82, 0x66, (байт) 0xca,
            0x60, (байт) 0xc0, 0x29, 0x23, (байт) 0xab, 0x0d, 0x53, 0x4e, 0x6f,
            (байт) 0xd5, (байт) 0xdb, 0x37, 0x45, (байт) 0xde, (байт) 0xfd,
            (байт) 0x8e, 0x2f, 0x03, (байт) 0xff, 0x6a, 0x72, 0x6d, 0x6c, 0x5b,
            0x51, (байт) 0x8d, 0x1b, (байт) 0xaf, (байт) 0x92, (байт) 0xbb,
            (байт) 0xdd, (байт) 0xbc, 0x7f, 0x11, (байт) 0xd9, 0x5c, 0x41,
            0x1f, 0x10, 0x5a, (байт) 0xd8, 0x0a, (байт) 0xc1, 0x31,
            (байт) 0x88, (байт) 0xa5, (байт) 0xcd, 0x7b, (байт) 0xbd, 0x2d,
            0x74, (байт) 0xd0, 0x12, (байт) 0xb8, (байт) 0xe5, (байт) 0xb4,
            (байт) 0xb0, (байт) 0x89, 0x69, (байт) 0x97, 0x4a, 0x0c,
            (байт) 0x96, 0x77, 0x7e, 0x65, (байт) 0xb9, (байт) 0xf1, 0x09,
            (байт) 0xc5, 0x6e, (байт) 0xc6, (байт) 0x84, 0x18, (байт) 0xf0,
            0x7d, (байт) 0xec, 0x3a, (байт) 0xdc, 0x4d, 0x20, 0x79,
            (байт) 0xee, 0x5f, 0x3e, (байт) 0xd7, (байт) 0xcb, 0x39, 0x48 };

    приватний 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) {
        повернення 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) {
        повернення B ^ Rotl(B, 2) ^ Rotl(B, 10) ^ Rotl(B, 18) ^ Rotl(B, 24);
        повернення B^(B<<2|B>>>30)^(B<<10|B>>>22)^(B<<18|B>>>14)^(B<<24|B>>>8);
    }

    private int L2(int B) {
        повернення B ^ Rotl(B, 13) ^ Rotl(B, 23);
        повернення B^(B<<13|B>>>19)^(B<<23|B>>>9);
    }

    void SMS4Crypt(byte[] Вхід, байт[] Вихід, int[] rk) {
        інтуїція R, середня, x0, x1, x2, x3;
        int[] x = новий int[4];
        int[] tmp = новий int[4];
        для (int i = 0; I < 4; i++) {
            tmp[0] = Вхід[0 + 4 * i] & 0xff;
            tmp[1] = Вхід[1 + 4 * i] & 0xff;
            tmp[2] = Input[2 + 4 * i] & 0xff;
            tmp[3] = Вхід[3 + 4 * i] & 0xff;
            x= tmp[0] << 24 | tmp[1] << 16 | tmp[2] << 8 | tmp[3];
            x=(Вхід[0+4*i]<<24| Input[1+4*i]<<16| Input[2+4*i]<<8| Input[3+4*i]);
        }
        для (r = 0; r < 32; r += 4) {
            середина = x[1] ^ x[2] ^ x[3] ^ rk[r + 0];
            mid = ByteSub(mid);
            x[0] = x[0] ^ L1(середина); x4

            середина = x[2] ^ x[3] ^ x[0] ^ rk[r + 1];
            mid = ByteSub(mid);
            x[1] = x[1] ^ L1(середина); x5

            середина = x[3] ^ x[0] ^ x[1] ^ rk[r + 2];
            mid = ByteSub(mid);
            x[2] = x[2] ^ L1(середина); x6

            середина = x[0] ^ x[1] ^ x[2] ^ rk[r + 3];
            mid = ByteSub(mid);
            x[3] = x[3] ^ L1(середина); x7
        }

        Реверс
        для (int j = 0; j < 16; j += 4) {
            Вихід[j] = (байт) (x[3 - j / 4] >>> 24 & 0xFF);
            Output[j + 1] = (байт) (x[3 - j / 4] >>> 16 & 0xFF);
            Output[j + 2] = (байт) (x[3 - j / 4] >>> 8 & 0xFF);
            Output[j + 3] = (байт) (x[3 - j / 4] & 0xFF);
        }
    }

    private void SMS4KeyExt(byte[] Key, int[] rk, int CryptFlag) {
        Інт-Р, Мід;
        int[] x = новий int[4];
        int[] tmp = новий int[4];
        для (int i = 0; I < 4; i++) {
            tmp[0] = Ключ[0 + 4 * i] & 0xFF;
            tmp[1] = Key[1 + 4 * i] & 0xff;
            tmp[2] = Key[2 + 4 * i] & 0xff;
            tmp[3] = Key[3 + 4 * i] & 0xff;
            x= tmp[0] << 24 | tmp[1] << 16 | tmp[2] << 8 | tmp[3];
            x=Ключ[0+4*i]<<24| Ключ[1+4*i]<<16| Key[2+4*i]<<8| Ключ[3+4*i];
        }
        x[0] ^= 0xa3b1bac6;
        x[1] ^= 0x56aa3350;
        x[2] ^= 0x677d9197;
        x[3] ^= 0xb27022dc;
        для (r = 0; r < 32; r += 4) {
            середина = x[1] ^ x[2] ^ x[3] ^ CK[r + 0];
            mid = ByteSub(mid);
            rk[r + 0] = x[0] ^= L2(середина); rk0=K4

            середина = x[2] ^ x[3] ^ x[0] ^ CK[r + 1];
            mid = ByteSub(mid);
            rk[r + 1] = x[1] ^= L2(середина); rk1=K5

            середина = x[3] ^ x[0] ^ x[1] ^ CK[r + 2];
            mid = ByteSub(mid);
            rk[r + 2] = x[2] ^= L2(середина); rk2=K6

            середина = x[0] ^ x[1] ^ x[2] ^ CK[r + 3];
            mid = ByteSub(mid);
            rk[r + 3] = x[3] ^= L2(середина); rk3=K7
        }

        Розшифруйте порядок клавіші колеса: rk31, rk30,...,rk0
        якщо (CryptFlag == ДЕШИФРУВАННЯ) {
            для (r = 0; р < 16; r++) {
                середина = rk[r];
                rk[r] = rk[31 - r];
                rk[31 - r] = середній;
            }
        }
    }

    public int sms4(byte[] in, int inLen, byte[] key, byte[] out, int CryptFlag) {
        int point = 0;
        int[] round_key = новий int[ROUND];
        int[] round_key={0};
        SMS4KeyExt(ключ, round_key, CryptFlag);
        байт[] вхід = новий байт[16];
        байт[] вихід = новий байт[16];

        тоді як (inLen >= БЛОК) {
            input = Arrays.copyOfRange(in, point, point + 16);
            output=Arrays.copyOfRange(out, point, point+16);
            SMS4Crypt(вхід, вихід, round_key);
            System.arraycopy (вихід, 0, вихід, точка, БЛОК);
            inLen -= БЛОК;
            точка += БЛОК;
        }

        return 0;
    }
}

Упакований зовнішній інтерфейс:

На основі цього базового класу основні інтерфейси такі:



приватний статичний байт[] encode16(byte[] plain, byte[] key);
приватний статичний байт[] декодування16(байт[] шифр, ключ byte[]);
приватний статичний байт[] encode32(byte[] plain, byte[] key);
приватний статичний байт[] декодування32(байт[] шифр, ключ byte[]);
публічний статичний байт[] encodeSMS4(байт[] звичайний, ключ байт[]);
публічний статичний байт[] декодування SMS4(байт[] шифр, ключ byte[]);
публічний статичний рядковий декод, SMS4toString(байт[] шифр, байт[] ключ);

encode16(байт[], байт[]) — це інтерфейс для шифрування 16-бітного відкритого тексту та 16-бітних ключів;
Приватний статичний байт[] декодування16(байт[] шифр, ключ байт[]): є інтерфейсом для розшифрування 16-бітного шифротексту та 16-бітного ключа;
Приватний статичний байт[] encode32(byte[] plain, byte[] ключ): Це інтерфейс, який шифрує 32-бітний відкритий текст і 16-бітні ключі.
Приватний статичний байт[] декодування32(байт[] шифр, ключ байт[]): Це інтерфейс для розшифрування 32-бітного шифротексту та 16-бітних ключів.
публічний статичний байт[] encodeSMS4(byte[] plain, byte[] ключ): Це інтерфейс, який шифрує відкритий текст і 16-бітні ключі з необмеженою кількістю байтів.
публічний статичний байт[] декодування SMS4(байт[] шифр, байт[] ключ): Це інтерфейс для дешифрування шифротексту та 16-бітних ключів з необмеженою кількістю байтів.
публічний статичний рядковий декодSMS4toString(byte[] шифр, байт[] ключ): Це інтерфейс для дешифрування необмеженої кількості байтів шифротексту та 16-бітних ключів.
Код методу інтерфейсу:



публічний статичний байт[] encodeSMS4(Рядковий відкритий текст, байт[] ключ) {
        якщо (відкритий текст == null || plaintext.equals()) {
            return null;
        }
        для (int i = plaintext.getBytes().довжина % 16; Мені < 16; i++) {
            відкритий текст += '';
        }
        
        повернути SMS4.encodeSMS4(plaintext.getBytes(), ключ);
    }
   
    /**
     * Шифрування SMS4 з необмеженою довжиною відкритого тексту
     *
     * @param відкритий текст
     * @param тональність
     * @return
     */
    публічний статичний байт[] encodeSMS4(байт[] відкритий текст, байт[] ключ) {
        байт[] шифротекст = новий байт[plaintext.length];
        
        int k = 0;
        int plainLen = plaintext.length;
        тоді як (k + 16 <= plainLen) {
            байт[] cellPlain = новий байт[16];
            для (int i = 0; Мені < 16; i++) {
                cellPlain= відкритий текст[k + i];
            }
            byte[] cellCipher = encode16(cellPlain, key);
            для (int i = 0; i < cellCipher.length; i++) {
                ciphertext[k + i] = cellCipher;
            }
            
            k += 16;
        }

        повернення шифротексту;
    }

    /**
     * Розшифрування SMS4 без обмеження на довжину відкритого тексту
     *
     * @param шифротекст
     * @param тональність
     * @return
     */
    публічний статичний байт[] декодування SMS4(байт[] шифротекст, ключ byte[] {
        байт[] відкритий текст = новий байт[ciphertext.length];
        
        int k = 0;
        int cipherLen = ciphertext.length;
        тоді як (k + 16 <= cipherLen) {
            byte[] cellCipher = новий байт[16];
            для (int i = 0; Мені < 16; i++) {
                cellCipher= шифротекст[k + i];
            }
            byte[] cellPlain = decode16(cellCipher, ключ);
            для (int i = 0; i < cellPlain.length; i++) {
                відкритий текст[k + i] = cellPlain;
            }
            
            k += 16;
        }
        
        поверніть відкритий текст;
    }

    /**
     * Дешифрування для отримання рядків відкритого тексту
     * @param шифротекст
     * @param тональність
     * @return
     */
    публічний статичний рядковий декодування SMS4toString(byte[] шифрований текст, ключ byte[] ) {
        байт[] відкритий текст = новий байт[ciphertext.length];
        відкритий текст = декодування SMS4 (шифротекст, ключ);
        повернути новий рядок (відкритий текст);
    }

    /**
     * Лише 16-бітний відкритий текст шифрується
     *
     * @param відкритий текст
     * @param тональність
     * @return
     */
    Приватний статичний байт[] encode16(byte[] відкритий текст, ключ byte[] {
        байт[] шифр = новий байт[16];
        SMS4 sm4 = новий SMS4();
        sm4.sms4(відкритий текст, 16, ключ, шифр, ШИФРУВАННЯ);

        шифр повернення;
    }

    /**
     * Розшифровується лише 16-бітний шифротекст
     *
     * @param відкритий текст
     * @param тональність
     * @return
     */
    Приватний статичний байт[] декодування16(байт[] шифротекст, ключ байт[] {
        байт[] простий = новий байт[16];
        SMS4 sm4 = новий SMS4();
        sm4.sms4 (шифротекст, 16, ключ, простий, ДЕШИФРУВАННЯ);

        повернення рівно;
    }
Я не буду вводити лише 32-бітне відкрите шифрування, яке дуже схоже на метод лише 16-бітного відкритого тексту.


Базовий алгоритм шифрування та дешифрування без обмеження довжини відкритого тексту базується на цьому засіданні шифрування та дешифрування лише 16 біт. Для відкритого тексту більше 16 біт тут використовується шифрування пакетів. Якщо ви зустрічаєте відкритий текст, наприклад 30 бітів, які не можна ділити на 16, один із способів заповнити його — дотягнути до того часу, поки він не буде ділим на 16. В принципі, лише найменше число можна поділити на 16, звісно, якщо ви задоволені, не має значення, чи збільшите його, бо це символ завершення.

Шифрування пакетів полягає в тому, щоб зашифрувати кожен 16-бітний відкритий текст один раз, а потім знову зібрати зашифрований 16-бітний шифротекст у новий шифротекст. Під час дешифрування його також розділяють на один 16-бітний фрагмент, а потім кілька з цих розшифрованих відкритих текстів збираються у новий відкритий текст.



Демонстрація використання:



Ключ
        byte[] key = { 0x01, 0x23, 0x45, 0x67, (байт) 0x89, (байт) 0xab,
                (байт) 0xcd, (байт) 0xef, (байт) 0xfe, (байт) 0xdc,
                (байт) 0xba, (байт) 0x98, 0x76, 0x54, 0x32, 0x10 };

        String newString = Кодування, привіт!; Відкритий текст
        
        byte[] enOut = SMS4.encodeSMS4(newString, key);
        якщо (enOut == null) {
            Повернутися;
        }
        
        System.out.println(результат шифрування:);
        printBit(enOut);

        byte[] deOut = SMS4.decodeSMS4(enOut, ключ);
        System.out.println(
результат дешифрування (байт повернення[]) :);
        printBit(deOut);

        String deOutStr = SMS4.decodeSMS4toString(enOut, key);
        System.out.println(
Розшифруйте результат (поверніть рядок):
+ deOutStr);
 Орендодавець| Опубліковано 08.12.2015 22:25:41 |
Сяо Чжажа Опубліковано 2015-12-8 22:19
Вступ до SMS4:

Цей алгоритм є алгоритмом групування. Алгоритм має довжину пакета 128 біт, а довжина ключа — 128 біт, що становить 16 байт. ...

Ти копіюєш обличчя всередині? Я запускав цей алгоритм на комп'ютері кілька разів, але досі не знайомий із C# у Java-налагодженні, можливо, не знаю кожного його кроку в деталях і ще не зрозумів принцип його роботи. Java, знаєш, як налагодити всі його змінні?
Опубліковано 08.12.2015 22:40:48 |

Це має бути для встановлення точки зупину: ключ F5 і клавіша F6 — це однокрокова налагодження, F5 — це крок, тобто введення рядкового коду для виконання, F6 — це крок, тобто виконання коду рядка, переход до наступного рядка
 Орендодавець| Опубліковано 08.12.2015 23:07:37 |
Опубліковано 2015-12-8 22:40
Це має бути для встановлення точки зупину, ключ Myeclipse breakpoint F5 і клавіша F6 обидва є однокроковими налагодженнями, F5 — це крок, тобто вводити код цього рядка для виконання ...

Я точно знаю, але не знаю його конкретного процесу і не знаю, коли і де дійду до якого етапу специфікації. Було б добре, якби ти зрозумів
Застереження:
Усе програмне забезпечення, програмні матеріали або статті, опубліковані Code Farmer Network, призначені лише для навчання та досліджень; Вищезазначений контент не повинен використовуватися в комерційних чи незаконних цілях, інакше користувачі несуть усі наслідки. Інформація на цьому сайті надходить з Інтернету, і спори щодо авторських прав не мають до цього сайту. Ви повинні повністю видалити вищезазначений контент зі свого комп'ютера протягом 24 годин після завантаження. Якщо вам подобається програма, будь ласка, підтримуйте справжнє програмне забезпечення, купуйте реєстрацію та отримайте кращі справжні послуги. Якщо є будь-яке порушення, будь ласка, зв'яжіться з нами електронною поштою.

Mail To:help@itsvse.com