Uso de OpenSSL EVP
EVP encapsula principalmente las siguientes funciones:
1) Se ha implementado la codificación y decodificación BIO BASE64.
2) Se ha implementado el cifrado y descifrado de información biológica; ;;
p>3) Implementar biología abstracta
4) Implementar io confiable
5) Encapsular algoritmo de resumen
6) Encapsular algoritmo de cifrado y descifrado simétrico
7) Encapsula cifrado de clave asimétrica (clave pública), descifrado (clave privada), firma y verificación y funciones auxiliares
8) Basado; en Cifrado de contraseña (PBE);
9) Procesamiento de clave simétrica
10) Sobre digital: el sobre digital utiliza la clave pública de la otra parte para cifrar la clave simétrica; clave Cifrar datos. Al enviar a la otra parte, el texto cifrado de clave simétrica y el texto cifrado de datos se envían al mismo tiempo. El receptor primero descifra el texto cifrado clave con su propia clave privada para obtener la clave simétrica y luego la usa para descifrar los datos.
11) Otras funciones auxiliares.
Este artículo asume que tienes OpenSSL instalado y tienes una copia del código fuente de 1.1.1.
Los archivos de encabezado relacionados con EVP están en evp.h y los archivos fuente están en el directorio crypto/evp.
Debido a que las funciones de EVP son demasiado poderosas y mi energía y nivel son limitados, por el momento solo extraeré y explicaré algunas funciones.
Esta estructura define el método abstracto del algoritmo de resumen. Significado del campo principal:
El tipo NID del algoritmo abstracto.
PKEY_TYPE: clave NID asociada al algoritmo de resumen.
MD_size: tamaño de salida de los valores agregados.
Bandera - bandera interna.
Función init-inicialización.
Actualizar - Ingresar a la función de cálculo.
Función de cálculo de salida final.
Copiar: función de copia del contexto de la operación de resumen.
Función de limpieza del contexto de la operación Clean-Aggregation.
block _ size: el tamaño de agrupación de la operación de resumen.
Tamaño CTX: tamaño del búfer del paquete de operación de resumen.
MD_CTRL: resume las funciones de control del comando de operación.
Los algoritmos de resumen admitidos incluyen:
const EVP _ MD * EVP _ MD5(void);
const EVP _ MD * EVP _ sha 1(void); ;
const EVP_MD * EVP_sha 256(void);
const EVP_MD * EVP_sha 512(void);
Con EVP_md5() es un ejemplo. El valor es:
Las siguientes funciones consultan la información de atributos de md:
A veces no estamos familiarizados con el algoritmo de resumen utilizado y estas funciones son muy útiles.
EVP_MD_CTX*EVP_MD_CTX_new(void);
void EVP_MD_CTX_free(EVP_MD_CTX*CTX); p>
Estas dos funciones se utilizan para crear y liberar objetos de contexto de resumen simétricos.
int EVP _ DigestInit(EVP _ MD _ CTX * CTX, const EVP _ MD * type);
El contexto abstracto se inicializa y el tipo es una colección abstracta de algoritmos abstractos.
1 devuelve éxito, 0 devuelve fracaso.
int EVP_digest update(EVP_MD_CTX *CTX, const void *d, size_t CNT);
Ingrese un dato en la estructura de esponja calculada en el resumen.
1 devuelve éxito, 0 devuelve fracaso.
int EVP_digest final(EVP_MD_CTX *CTX, unsigned char *md, unsigned int *s);
Genera el resumen final y genera el valor y la longitud del resumen.
1 devuelve éxito, 0 devuelve fracaso.
int EVP_Digest(const void *data, size_t count, unsigned char *md, unsigned int *size, const EVP_MD *type, ENGINE *impl
Usar empaquetado una sola vez); El método calcula el resumen de un pequeño dato.
1 devuelve éxito, 0 devuelve fracaso.
Estructura evp_cipher_st {
int nid
int block _ size
/*Valor predeterminado de cifrado de longitud variable/
int key _ len
int iv _ len
/Varios indicadores/
Indicador largo sin firmar;
/tecla init /
int (init) (EVP_CIPHER_CTX *ctx, const unsigned char *key,
const unsigned char iv, int enc);
/Encrypt/Decrypt data/
int(do _ CIPHER)(EVP _ CIPHER _ CTX * CTX, carácter sin firmar *salida,
const carácter sin firmar en, tamaño _ t inl);
/ cleanup ctx /
int(clean up)(EVP _ CIPHER _ CTX
/¿Qué tamaño debe tener CTX-& gt; /p>
int ctx_size
/llenar ASN1_TYPE con parámetros/
int(set_ASN 1_parameters)(EVP_CIPHER_CTX *,ASN 1_TYPE);
/Get parámetros de ASN1_TYPE/
int(get_ASN 1_parameters)(EVP_CIPHER_CTX *,ASN 1_TYPE) ;
/Operaciones varias/
int (ctrl) (EVP_CIPHER_CTX *, int type, int arg, void ptr);
/Datos de la aplicación*/
void app_data
}/EVP_CIPHER */; p>
typedef struct EVP _ CIPHER _ ST EVP _ CIPHER;
Esta estructura define un método abstracto para algoritmos de cifrado simétrico. Significado del campo principal:
NID-NID del algoritmo de cifrado.
block_size-tamaño del paquete.
key_len - longitud de la clave.
iv _ len - longitud inicial del vector.
Bandera - bandera interna.
Función init-inicialización.
función de operación intermedia do_cipher.
Limpieza-la función de operación final.
Tamaño CTX - tamaño de contexto.
Función de control Ctrl.
app_data-datos de la aplicación.
Los algoritmos de cifrado y descifrado abstractos criptográficos admitidos incluyen:
const EVP _ CIPHER * EVP _ des _ ECB(void);
const EVP _ CIPHER * EVP); _ des _ ede 3(void);
const EVP _ CIPHER * EVP _ AES _ 128 _ ECB (void);
const EVP _ CIPHER * EVP _ AES _ 128 _ CBC(void);
La siguiente función consulta la información del atributo de la contraseña:
int EVP _ CIPHER _ NID (const EVP _ CIPHER * CIPHER
<); p> int EVP _ CIPHER _ type(const EVP _ CIPHER * CTX#Definir EVP _ CIPHER _ nombre(e)OBJ _ nid2sn(EVP _ CIPHER _ NID(e))
int EVP_CIPHER_block_size(const EVP_CIPHER * CIPHER);
int EVP_CIPHER_key_length (const EVP_CIPHER * CIPHER); _ iv _ length(const EVP _ CIPHER * CIPHER);
A veces no estamos familiarizados con el algoritmo de cifrado utilizado, estas funciones son útiles.
EVP _ CIPHER _ CTX * EVP _ CIPHER _ CTX _ nuevo(void);
void EVP _ CIPHER _ CTX _ gratis(EVP _ CIPHER _ CTX * c); /p>
Estas dos funciones se utilizan para crear y liberar objetos de contexto de cifrado y descifrado simétricos.
int EVP_CIPHER_CTX_set_key_length(EVP_CIPHER_CTX * x, int key len);
Cuando la longitud de la clave del algoritmo simétrico es variable, establezca la longitud de la clave del algoritmo simétrico.
1 devuelve éxito, 0 devuelve fracaso.
int EVP_CIPHER_CTX_set_padding(EVP_CIPHER_CTX * c, int pad);
Establece el relleno del algoritmo simétrico, que a veces implica relleno.
Pad toma los valores 0 y 1. Cuando pad es 1, se utiliza relleno. La estrategia de llenado predeterminada adopta la especificación PKCS5, es decir, cuando el último paquete se llena con n bytes, su valor de llenado es n.
1 devuelve éxito, 0 devuelve fracaso.
int EVP _ encrypt init(EVP _ CIPHER _ CTX * CTX, const EVP_CIPHER *cipher, const unsigned char *key, const unsigned char * iv
Inicializar contexto de cifrado simétrico); .
Si se agrega 1 correctamente, se devolverá 0 si falla.
int EVP _ encrypt update(EVP _ CIPHER _ CTX * CTX, unsigned char *out, int *outl, const unsigned char *in, int inl
Cifrar texto sin formato); .
Si se agrega 1 correctamente, se devolverá 0 si falla. En caso de éxito, outl genera la longitud del texto cifrado.
int EVP_encrypt final(EVP_CIPHER_CTX *CTX, unsigned char *out, int *outl);
Cifre el texto plano restante.
Si se agrega 1 correctamente, se devolverá 0 si falla. En caso de éxito, outl genera la longitud del texto cifrado.
int EVP_decrypt init(EVP_CIPHER_CTX * CTX, const EVP_CIPHER *cipher, const unsigned char *key, const unsigned char * iv);
Inicializar el contexto de descifrado simétrico.
Si se agrega 1 correctamente, se devolverá 0 si falla.
int EVP _ decrypt update(EVP _ CIPHER _ CTX * CTX, unsigned char *out, int *outl, const unsigned char *in, int inl
Descifrar texto cifrado).
Si se agrega 1 correctamente, se devolverá 0 si falla. Si tiene éxito, outl genera la longitud del texto sin formato.
int EVP_decrypt final(EVP_CIPHER_CTX *CTX, unsigned char *outm, int *outl);
Descifra el texto cifrado restante.
Si se agrega 1 correctamente, se devolverá 0 si falla. Si tiene éxito, outl genera la longitud del texto sin formato.
int EVP_BytesToKey(const EVP_CIPHER *tipo, const EVP_MD *md,
const unsigned char *salt,
const unsigned char * datos, int datal, int count
unsigned char *key, unsigned char * iv);
Calcular la función de clave, que se calcula en función del tipo de algoritmo, el algoritmo abstracto, la sal y los datos de entrada Una clave simétrica e inicialización vector iv. La longitud de la clave de adición.
Esta función se utiliza en la función PEM_do_header() para generar una clave basada en la contraseña.
Esta estructura define el contenedor de almacenamiento para información de claves asimétricas. Significado del campo principal:
Escriba NID del algoritmo de cifrado asimétrico.
save_type: el tipo de PKEY guardado.
PKEY: puntero PKEY guardado, como el puntero de estructura RSA.
EVP _ PKEY * EVP _ PKEY _ new(void);
void EVP _ PKEY _ free(EVP _ PKEY * PKEY); Las funciones se utilizan para crear y liberar objetos de contexto PKEY.
int EVP _ PKEY _ asignar(EVP _ PKEY * PKEY, int type, void * key);
Estructura de contexto que especifica el tipo de algoritmo para la asociación PKEY. Por ejemplo, la definición de macro asociada con RSA es la siguiente:
#Define EVP_SignInit(a, b) EVP_DigestInit(a, b)
#Define EVP_SignUpdate(a, b, c ) EVP_DigestUpdate(a, b, c)
int EVP _ sign final(EVP _ MD _ CTX * CTX, char unsigned *md, int unsigned *s,
EVP _ PKEY *PKEY );
Cálculo de firma. Como puede verse en la definición de la macro, la abstracción en realidad se calcula primero y luego se cifra con la clave privada RSA.
Si se agrega 1 correctamente, se devolverá 0 si falla.
#Definir EVP_VerifyInit(a, b) EVP_DigestInit(a, b)
#Definir EVP_VerifyUpdate(a, b, c) EVP_DigestUpdate(a, b, c)
int EVP_verify final(EVP_MD_CTX *CTX, const unsigned char *sigbuf
unsigned int siglen, EVP_PKEY *PKEY);
Comprueba y firma Calcula el resultado. Como se puede ver en la definición de la macro, el resumen se calcula primero, luego la firma se descifra con la clave pública RSA y luego se compara con el resumen.
Si se agrega 1 correctamente, se devolverá 0 si falla.
El siguiente ejemplo demuestra el proceso de cálculo abstracto utilizando dos métodos MD5.
Salida:
EVP_DigestInit() ret:[1]
EVP _ digest update() ret:[1]
EVP_DigestFinal () ret:[1]
e 380 e 88 e 8d 09 ebf 8d 8659 a 15b 0 ea 70 b 5
EVP_Digest() ret:1
e 380 e 88 e 8d 09 ebf 8d 8659 a 15b 0 ea 70 b 5
El siguiente ejemplo demuestra el proceso de cifrado y descifrado utilizando DES. Para facilitar la implementación del programa, utilice std::string como excepción.
Salida:
EVP_EncryptInit() ret:[1]
EVP_encrypt update()ret:[1]
Diablo:[ 24]
EVP _ encrypt final()ret:[1]
nCipherLen:[8]
Tamaño de contraseña:[32]
EVP_DecryptInit() ret:[1]
EVP _ decrypt update() ret:[1]
nTextLen:[24]
EVP _ decrypt final()ret:[1]
nTextLen:[2]
Tamaño del texto:[26]Texto:[abcdefghijklmnopqrstuvwxyz]
El siguiente ejemplo demuestra el Se explica el proceso de uso de SHA1 para los cálculos de firma RSA y verificación de firma.
Salida:
RSA _ generar _ clave _ ex()ret:[1]
EVP _ PKEY _ asignar _ RSA()ret:[1 ]
EVP_SignInit() retirada:[1]
EVP_SignUpdate() retirada:[1]
EVP_SignFinal() retirada:[1]
sha1 len:[64]
EVP_VerifyInit() ret:[1]
EVP _ verificar actualización()ret:[1]
EVP_VerifyFinal () retirar:[1]