Este artículo es un artículo espejo de traducción automática, por favor haga clic aquí para saltar al artículo original.

Vista: 16332|Respuesta: 4

[Algoritmo] Algoritmo SMS4, que es un algoritmo de criptografía por bloques simétrico

[Copiar enlace]
Publicado en 8/12/2015 21:49:35 | | |
Esto es un algoritmo de criptografía por bloques, pero él usa muchas cosas, y ahora hay un código fuente específico en Internet, pero este código sigue teniendo cierto valor de investigación; si también te interesa, puedes venir y comunicarte y aprender juntos. De hecho, no tiene sentido darte un código completo, pero aun así adjunto la dirección completa del código a la http://www.2cto.com/kf/201501/369374.html
También hay una caja S en ella, que es muy importante, y que se usa en el algoritmo DES, así que la sugerencia de mi compañero es que entienda claramente la caja S del algoritmo DES, para poder saber a qué se refiere la especificación de este algoritmo SMS4. La especificación no está adjunta.





Anterior:Parece que este lugar no se ha actualizado en mucho tiempo, y actualizaré el lenguaje C todos los días en el futuro.
Próximo:Vídeo en lengua C, versión completa
Publicado en 8/12/2015 22:19:05 |

Introducción a SMS4:

Este algoritmo es un algoritmo de agrupación. El algoritmo tiene una longitud de paquete de 128 bits y una longitud de clave de 128 bits, que son 16 bytes. Tanto el algoritmo de cifrado como el algoritmo de expansión de claves adoptan una estructura de iteración no lineal de 32 rondas. El algoritmo de descifrado tiene la misma estructura que el algoritmo de cifrado, salvo que el orden de uso de la clave de ronda se invierte, y la clave de la rueda de descifrado es el orden inverso de la clave de la rueda de cifrado. En todas las clases base de SMS4, verás que las funciones base de cifrado y descifrado son las mismas, pero se necesita un bit de bandera de tipo int para determinar si está cifrado o descifrado.

Conceptos básicos del algoritmo de cifrado SMS4:



clase pública SMS4 {

    private static final int ENCRYPT = 1;
    privado estático final int DECRYPT = 0;
    final pública estática de la RONDA de la Int = 32;
    estática privada final int BLOCK = 16;

    byte privado[] 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 };

    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) {
        devolver x << y | x >>> (32 - y);
    }

    private int ByteSub(int A) {
        Retorno (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);
        retorno 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);
        retorno B^(B<<13|B>>>19)^(B<<23|B>>>9);
    }

    void SMS4Crypt(byte[] Entrada, byte[] Salida, int[] rk) {
        int r, mid, x0, x1, x2, x3;
        int[] x = nuevo int[4];
        int[] tmp = nuevo int[4];
        para (int i = 0; Yo < 4; i++) {
            tmp[0] = Entrada[0 + 4 * i] & 0xff;
            tmp[1] = Entrada[1 + 4 * i] & 0xff;
            tmp[2] = Entrada[2 + 4 * i] & 0xff;
            tmp[3] = Entrada[3 + 4 * i] & 0xff;
            x= tmp[0] << 24 | TMP[1] << 16 | TMP[2] << 8 | tmp[3];
            x=(Entrada[0+4*i]<<24| Input[1+4*i]<<16| Entrada[2+4*i]<<8| Input[3+4*i]);
        }
        para (r = 0; r < 32; r += 4) {
            mid = x[1] ^ x[2] ^ x[3] ^ rk[r + 0];
            mid = ByteSub(mid);
            x[0] = x[0] ^ L1(medio); x4

            mid = x[2] ^ x[3] ^ x[0] ^ rk[r + 1];
            mid = ByteSub(mid);
            x[1] = x[1] ^ L1(medio); x5

            mid = x[3] ^ x[0] ^ x[1] ^ rk[r + 2];
            mid = ByteSub(mid);
            x[2] = x[2] ^ L1(medio); x6

            mid = x[0] ^ x[1] ^ x[2] ^ rk[r + 3];
            mid = ByteSub(mid);
            x[3] = x[3] ^ L1(medio); x7
        }

        Marcha atrás
        para (int j = 0; j < 16; j += 4) {
            Salida[j] = (byte) (x[3 - j / 4] >>> 24 & 0xFF);
            Salida[j + 1] = (byte) (x[3 - j / 4] >>> 16 & 0xFF);
            Salida[j + 2] = (byte) (x[3 - j / 4] >>> 8 & 0xFF);
            Salida[j + 3] = (byte) (x[3 - j / 4] & 0xFF);
        }
    }

    private void SMS4KeyExt(byte[] Key, int[] rk, int CryptFlag) {
        int r, mid;
        int[] x = nuevo int[4];
        int[] tmp = nuevo int[4];
        para (int i = 0; Yo < 4; i++) {
            tmp[0] = Clave[0 + 4 * i] & 0xFF;
            tmp[1] = Clave[1 + 4 * i] & 0xff;
            tmp[2] = Clave[2 + 4 * i] & 0xff;
            tmp[3] = Clave[3 + 4 * i] & 0xff;
            x= tmp[0] << 24 | TMP[1] << 16 | TMP[2] << 8 | tmp[3];
            x=Clave[0+4*i]<<24| Clave[1+4*i]<<16| Clave[2+4*i]<<8| Clave[3+4*i];
        }
        x[0] ^= 0xa3b1bac6;
        x[1] ^= 0x56aa3350;
        x[2] ^= 0x677d9197;
        x[3] ^= 0xb27022dc;
        para (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(mid); rk0=K4

            mid = x[2] ^ x[3] ^ x[0] ^ CK[r + 1];
            mid = ByteSub(mid);
            rk[r + 1] = x[1] ^= L2(mid); rk1=K5

            mid = x[3] ^ x[0] ^ x[1] ^ CK[r + 2];
            mid = ByteSub(mid);
            rk[r + 2] = x[2] ^= L2(mid); rk2=K6

            mid = x[0] ^ x[1] ^ x[2] ^ CK[r + 3];
            mid = ByteSub(mid);
            rk[r + 3] = x[3] ^= L2(mid); rk3=K7
        }

        Descifrar el orden de la clave de la rueda: rk31, rk30,...,rk0
        if (CryptFlag == DECRYPT) {
            para (r = 0; r < 16; r++) {
                mid = rk[r];
                rk[r] = rk[31 - r];
                rk[31 - r] = mid;
            }
        }
    }

    public int sms4(byte[] in, int inLen, byte[] clave, byte[] out, int CryptFlag) {
        punto de inteligencia = 0;
        int[] round_key = nueva int[RONDA];
        int[] round_key={0};
        SMS4KeyExt (clave, round_key, CryptFlag);
        entrada de byte[] = nuevo byte[16];
        salida de byte[] = nuevo byte[16];

        while (inLen >= BLOCK) {
            entrada = Arrays.copiaDeRango(in, punto, punto + 16);
            salida=Arrays.copiaDeRango(salida, punto, punto+16);
            SMS4Crypt (entrada, salida round_key);
            System.arraycopy(salida, 0, salida, punto, BLOQUE);
            inLen -= BLOQUEO;
            punto += BLOQUEO;
        }

        return 0;
    }
}

Interfaz externa empaquetada:

Basándose en esta clase básica, las interfaces principales son las siguientes:



byte estático privado[] encode16(byte[] plain, byte[] key);
byte estático privado[] decode16(cifrado byte[] clave byte[]);
byte estático privado[] encode32(byte[] plain, byte[] key);
byte estático privado[] decode32(cifrado byte[], clave byte[]);
byte estático público[] encodeSMS4(byte[] plain, byte[] key);
byte estático público[] decodeSMS4(cifrado byte[] clave de byte[]);
decodificación estática pública de cadenasSMS4toString(cifrado byte[] clave);

encode16(byte[], byte[]) es una interfaz para cifrado de texto plano de 16 bits y claves de 16 bits;
Byte estático privado[] Decode16(cifrado byte[] clave: es una interfaz para descifrar texto cifrado de 16 bits y clave de 16 bits;
byte estático privado[] encode32(byte[] simple, byte[] clave): Esta es una interfaz que cifra texto plano de 32 bits y claves de 16 bits.
Byte estático privado[] decode32(cifrado byte[], clave byte[]): Esta es una interfaz para descifrar texto cifrado de 32 bits y claves de 16 bits.
byte estático público[] encodeSMS4(byte[] plano, clave byte[]): Esta es una interfaz que cifra texto plano y claves de 16 bits con un número ilimitado de bytes.
byte estático público[] decodeSMS4(byte[] cifrado, clave byte[]): Esta es una interfaz para descifrar texto cifrado y claves de 16 bits con un número ilimitado de bytes.
cifrado estático público de cadenasSMS4toString(byte[] cifrado, clave byte[]): Esta es una interfaz para descifrar bytes ilimitados de texto cifrado y claves de 16 bits.
Código de método de interfaz:



byte estático público[] encodeSMS4(String plaintext, byte[] key) {
        if (texto plano == null || texto plano.iguales()) {
            return null;
        }
        para (int i = texto plano.getBytes().length % 16; < 16; i++) {
            texto plano += '';
        }
        
        return SMS4.encodeSMS4(texto plano.getBytes(), clave);
    }
   
    /**
     * Cifrado SMS4 con longitud ilimitada de texto plano
     *
     * @param texto plano
     * @param clave
     * @return
     */
    byte estático público[] encodeSMS4(byte[] texto plano, clave byte[]) {
        byte[] texto cifrado = nuevo byte[plaintext.length];
        
        int k = 0;
        int plainLen = texto plano.longitud;
        mientras que (k + 16 <= plainLen) {
            byte[] cellPlain = nuevo byte[16];
            para (int i = 0; < 16; i++) {
                cellPlain= texto plano[k + i];
            }
            byte[] cellCipher = encode16(cellPlain, key);
            para (int i = 0; i < cellCipher.length; i++) {
                texto cifrado[k + i] = celCifrado;
            }
            
            k += 16;
        }

        devolver texto cifrado;
    }

    /**
     * Descifrado en SMS4 sin límite de longitud de texto plano
     *
     * @param texto cifrado
     * @param clave
     * @return
     */
    byte estático público[] decodeSMS4(byte[] texto cifrado, clave de byte[] {
        byte[] texto plano = nuevo byte[cifrado.longitud];
        
        int k = 0;
        int cifradoLen = cifradotexto.longitud;
        mientras que (k + 16 <= cipherLen) {
            byte[] cellCipher = nuevo byte[16];
            para (int i = 0; < 16; i++) {
                cellCipher= texto cifrado[k + i];
            }
            byte[] cellPlain = decode16(cellCipher, clave);
            para (int i = 0; i < cellPlain.length; i++) {
                texto plano[k + i] = celdaPlano;
            }
            
            k += 16;
        }
        
        devolver texto plano;
    }

    /**
     * Descifrar para obtener cadenas de texto plano
     * @param texto cifrado
     * @param clave
     * @return
     */
    Cadena estática pública decodesSMS4toString(byte[] texto cifrado, byte[] clave) {
        byte[] texto plano = nuevo byte[cifrado.longitud];
        texto plano = decodeSMS4(texto cifrado, clave);
        return new String (texto plano);
    }

    /**
     * Solo el texto plano de 16 bits está cifrado
     *
     * @param texto plano
     * @param clave
     * @return
     */
    Byte estático privado[] encode16(byte[] texto plano, byte[] clave) {
        cifrado byte[] = nuevo byte[16];
        SMS4 sm4 = nuevo SMS4();
        sm4.sms4(texto plano, 16, clave, cifrado, ENCRIPTADO);

        devuelvo cifrado;
    }

    /**
     * Solo se descifra el texto cifrado de 16 bits
     *
     * @param texto plano
     * @param clave
     * @return
     */
    byte estático privado[] decode16(byte[] texto cifrado, byte[] clave) {
        byte[] plain = nuevo byte[16];
        SMS4 sm4 = nuevo SMS4();
        sm4.sms4(texto cifrado, 16, clave, plano, DECRYPT);

        regresar plano;
    }
No voy a introducir solo el cifrado de texto plano de 32 bits aquí, que es muy similar al método del texto plano de solo 16 bits.


El algoritmo básico para el cifrado y descifrado sin limitar la longitud del texto plano se basa en esta base de cifrar y descifrar solo 16 bits. Para texto plano mayor a 16 bits, aquí se utiliza cifrado de paquetes. Si te encuentras con texto plano como 30 bits que no se pueden dividir por 16, una forma de rellenarlo es hacerlo hasta que sea divisible por 16. En principio, solo el número más pequeño puede dividirse entre 16, por supuesto, si eres feliz, no importa si lo haces más grande, porque es el símbolo de cierre.

El cifrado de paquetes consiste en cifrar cada texto plano de 16 bits una vez, y luego reensamblar el texto cifrado de 16 bits en un nuevo texto cifrado. En el proceso de descifrado, también se divide en una única pieza de 16 bits, y luego varios de estos textos planos descifrados se reensamblan en un nuevo texto plano.



Demostración de uso:



Clave
        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 = ¡Codificación, hola!; Texto plano
        
        byte[] enOut = SMS4.encodeSMS4(newString, clave);
        if (enOut == null) {
            devolución;
        }
        
        System.out.println (resultado de cifrado:);
        printBit(enOut);

        byte[] deOut = SMS4.decodeSMS4(enOut, clave);
        System.out.println(
resultado de descifrado (byte de retorno[]) :);
        printBit(deOut);

        String deOutStr = SMS4.decodeSMS4toString(enOut, key);
        System.out.println(
Descifrar el resultado (return String):
+ deOutStr);
 Propietario| Publicado en 8/12/2015 22:25:41 |
Xiao Zhazha Publicado el 8-12-2015 22:19
Introducción a SMS4:

Este algoritmo es un algoritmo de agrupación. El algoritmo tiene una longitud de paquete de 128 bits y una longitud de clave de 128 bits, que son 16 bytes. ...

¿Estás copiando la cara que hay dentro? He ejecutado este algoritmo en el ordenador varias veces, pero todavía no estoy familiarizado con C# en la depuración de Java, y puede que no conozca cada uno de sus pasos con detalle, y aún no he descifrado el principio de sus detalles de trabajo. Java, ¿sabes cómo depurar todas sus variables?
Publicado en 8/12/2015 22:40:48 |

Debe ser para establecer el punto de interrupción, la clave F5 y la clave F6 del punto de interrupción de myeclipse son depuración de paso simple, F5 es paso a paso, es decir, introducir el código de línea para ejecutar, F6 es paso a paso, es decir, ejecutar el código de línea y saltar a la siguiente línea
 Propietario| Publicado en 8/12/2015 23:07:37 |
Publicado el 8-12-2015 a las 22:40
Debería ser para establecer el punto de interrupción, la clave F5 y la clave F6 de Myeclipse son ambas depuraciones de paso único, F5 es paso a paso, es decir, introducir el código de esta línea para ejecutar ...

Lo sé perfectamente, pero no conozco su proceso específico, ni cuándo ni dónde llegaré a cada paso de la especificación. Sería bueno que lo entendieras
Renuncia:
Todo el software, materiales de programación o artículos publicados por Code Farmer Network son únicamente para fines de aprendizaje e investigación; El contenido anterior no se utilizará con fines comerciales o ilegales; de lo contrario, los usuarios asumirán todas las consecuencias. La información de este sitio proviene de Internet, y las disputas de derechos de autor no tienen nada que ver con este sitio. Debes eliminar completamente el contenido anterior de tu ordenador en un plazo de 24 horas desde la descarga. Si te gusta el programa, por favor apoya el software genuino, compra el registro y obtén mejores servicios genuinos. Si hay alguna infracción, por favor contáctanos por correo electrónico.

Mail To:help@itsvse.com