Administrar claves de cifrado con AWS KMS en Node.js

itsgoingdown.org

La seguridad es muy importante al desarrollar aplicaciones. ¿Cómo encriptas los datos y administras las claves de cifrado en tu aplicación? El manejo exitoso de claves es crítico para la seguridad de un criptosistema. Aquí es donde entran en juego los KMS. Primero veamos qué es realmente un KMS.

Sistema clave de gestión (KMS)

De acuerdo con Wikipedia,

Un sistema de administración de claves (KMS), también conocido como sistema de administración de claves criptográficas (CKMS), es un enfoque integrado para generar, distribuir y administrar claves criptográficas para dispositivos y aplicaciones. En comparación con el término gestión de claves, un KMS se adapta a casos de uso específicos, como la actualización segura de software o la comunicación de máquina a máquina . En un enfoque holístico, cubre todos los aspectos de la seguridad, desde la generación segura de claves a través del intercambio seguro de claves hasta el manejo y almacenamiento seguro de claves en el cliente. Por lo tanto, un KMS incluye la funcionalidad de back-end para la generación , distribución y reemplazo de claves, así como la funcionalidad del cliente para inyectar claves, almacenar y administrar claves en los dispositivos. Con Internet of Things , KMS se convierte en una parte crucial para la seguridad de los dispositivos conectados.

Un KMS hace que su vida sea más fácil cuando se trata de la administración de claves y el cifrado.

AWS KMS

Ahora sabemos lo que es un sistema de gestión de claves. Hablemos brevemente de AWS KMS.

AWS KMS es un servicio de AWS que le facilita la administración de sus claves de cifrado. Utiliza Hardware Security Modules (HSM) en el back-end. AWS KMS está integrado con otros servicios de AWS. También es de bajo costo. AWS KMS proporciona control de acceso a sus claves para que pueda determinar quién puede acceder a ellas, cuándo se puede acceder a ellas y muchas otras opciones.

AWS KMS utiliza el algoritmo del Estándar de cifrado avanzado (AES) en el modo Galois / Counter (GCM) , conocido como AES-GCM. AWS KMS usa este algoritmo con claves secretas de 256 bits.

Los precios de AWS KMS se pueden ver aquí . El nivel gratuito incluye 20,000 solicitudes / mes.

Uso de AWS KMS con Node.js

En esta sección, voy a compartir cómo usar AWS KMS dentro de su aplicación Node.js. Voy a cubrir los siguientes temas aquí,

  • Cómo crear un CMK (Clave maestra de cliente).
  • Cómo adjuntar un usuario de IAM a CMK con una política de IP restringida.
  • Cómo cifrar datos utilizando CMK.
  • Cómo descifrar datos usando CMK.
  • Encriptación de sobres usando AWS KMS.
  • Contexto de encriptación (Intro)

Con eso dicho, quiero primero decir que no soy un experto en criptografía.

Cómo crear un CMK (Clave maestra de cliente)

Los recursos principales en AWS KMS son claves maestras de clientes (CMK). Los CMK son gestionados por los clientes o gestionados por AWS. Echemos un vistazo a cómo crear una clave maestra de cliente en AWS.

Inicie sesión en la consola de AWS y vaya a los servicios. Luego selecciona "IAM". Ahí, en el lado izquierdo, puede ver una sección llamada "Claves de cifrado". Navega a esa sección. Luego, selecciona "Crear clave" en la esquina superior izquierda.

Ingrese un alias para la clave y una descripción. En las opciones avanzadas, seleccione KMS. Aquí puede importar su propia clave externa si lo desea. No voy a tratar de cómo importar una clave externa aquí (también es bastante sencillo).

Haga clic en Siguiente. Agregue etiquetas (opcional) si lo requiere. Ve al siguiente paso otra vez. Si ya tiene un usuario de IAM creado (si no se salta la selección de un usuario. Crearemos un usuario más adelante) y si desea permitir que ese usuario acceda a esta tecla, seleccione el usuario de la lista y haga clic en siguiente. Finalmente termine el proceso. Tu clave se creará ahora.

Cómo adjuntar un usuario de IAM a CMK con una política restringida de IP

Ahora, si no tiene un usuario de IAM creado anteriormente, siga estos pasos para crear uno.

Vaya a "IAM" (como se muestra arriba). Seleccione "Usuarios" en el lado izquierdo. Seleccione "Agregar usuario" en la esquina superior izquierda. Complete los detalles requeridos. Un ejemplo se da a continuación.

Seleccione siguiente. Seleccione la opción "Adjuntar políticas existentes directamente". Luego selecciona "Crear política". Puede editar visualmente la política o editar el json de la política. Voy a editar el JSON aquí. Seleccione la pestaña "json". Utilizaré la siguiente política simple que solo permitirá el acceso al CMK desde una IP seleccionada. Puede seleccionar un rango de IP o puede personalizar la política de la manera que desee.

política

Después de eso, siga las instrucciones para guardar la política creada. Luego termine de crear el usuario. En la última página, se mostrarán la ID de la clave de acceso y la clave de acceso secreta del usuario nuevo. Descargue esa información. No podrá verlo después (pero puede crear nuevas credenciales de nuevo).

Ahora ve a las claves de cifrado y selecciona la clave que acabas de crear. Vaya a la sección "Usuarios clave" y seleccione "Agregar". Seleccione el usuario que ha creado. Entonces ese usuario se agregará a la lista permitida para el CMK que usted creó.

Los usuarios clave

Cómo cifrar datos utilizando CMK

¡Suficiente configuración, veamos cómo usar AWS KMS!

Estoy usando AWS SDK para Node.js aquí. Instalemos el paquete AWS SDK desde npm.

 npm instala aws-sdk 

La función siguiente encripta un búfer dado y emite el blob de texto de cifrado.

 function encrypt (buffer) { 
const kms = new aws.KMS ({
accessKeyId: 'AKCVBTRNOSMLTIA7RPQQ', // credenciales para su usuario de IAM
secretAccessKey: 'lJQtdIfH / Cup9AyaaHV8h2NnR / eKFIsZea5Vn0k', // credenciales para su usuario de IAM
región: 'ap-southeast-1'
});
return new Promise ((resolver, rechazar) => {
const params = {
KeyId: '965d2884-b2cd-4d79-8773-6b1f57133300', // El identificador del CMK a usar para el cifrado. Puede usar la ID de clave o nombre de recurso de Amazon (ARN) del CMK, o el nombre o ARN de un alias que hace referencia al CMK.
Texto sin formato: búfer // Los datos para encriptar.
};
kms.encrypt (params, (err, data) => {
si (err) {
rechazar (errar);
} else {
resolver (data.CiphertextBlob);
}
});
});
}

Cómo descifrar datos usando CMK

La función siguiente descifra un blob de texto de cifrado cifrado anteriormente y devuelve el búfer de texto sin formato.

 función descifrar (buffer) { 
const kms = new aws.KMS ({
accessKeyId: 'AKCVBTRNOSMLTIB7ROQQ',
secretAccessKey: 'lJQtdIfH / Cup9AyabHV9h2NnR / eKFIsZea2Vn0k',
región: 'ap-southeast-1'
});
return new Promise ((resolver, rechazar) => {
const params = {
CiphertextBlob: buffer // Los datos para descifrar.
};
kms.decrypt (params, (err, data) => {
si (err) {
rechazar (errar);
} else {
resolver (data.Plaintext);
}
});
});
}

El siguiente código encripta el texto "abc" y lo descifra e imprime el valor en la consola

 encriptar ( nuevo Buffer ('abc', 'utf-8')). then (decrypt) .then (plaintext => { 
console.log (plaintext.toString ('utf-8'));
});

Encriptación de sobres usando AWS KMS

AWS KMS tiene un límite de tamaño para encriptar datos directamente utilizando el CMK. Solo puede encriptar hasta 4 kilobytes de datos por solicitud. Si desea encriptar datos de mayor tamaño, por ejemplo un video, debe usar encriptación de sobre.

En el cifrado de sobre, generamos una clave de datos utilizando nuestro CMK en KMS. Al generar la clave de datos, AWS nos envía tanto la clave de texto sin cifrar como la clave encriptada (utilizando nuestro CMK). Luego usamos la clave de datos de texto sin formato generada para encriptar nuestros datos. Después de encriptar los datos, destruimos la clave de texto sin formato y mantenemos la clave encriptada con nosotros. Cuando queremos descifrar los datos, enviamos la clave cifrada a AWS KMS y recuperamos la clave de texto sin formato y continuamos con el descifrado.

Primero, necesitamos generar una clave de datos de AWS KMS. El siguiente diagrama representa ese procedimiento.

http://docs.aws.amazon.com

La siguiente función genera una clave de datos de AWS KMS.

 function generateDataKey () { 
const kms = new aws.KMS ({
accessKeyId: 'AKCVBTRNOSMLTIB7ROQQ',
secretAccessKey: 'lJQtdIfH / Cup9AyabHV9h2NnR / eKFIsZea2Vn0k',
región: 'ap-southeast-1'
});
return new Promise ((resolver, rechazar) => {
const params = {
KeyId: '965d2884-b2ab-4e78-8773-6b1f57133300', // El identificador del CMK a usar para encriptar la clave de datos. Puede usar la ID de clave o nombre de recurso de Amazon (ARN) del CMK, o el nombre o ARN de un alias que hace referencia al CMK.
KeySpec: 'AES_256' // Especifica el tipo de clave de datos a devolver.
};
kms.generateDataKey (params, (err, data) => {
si (err) {
rechazar (errar);
} else {
resolver (datos);
}
});
});
}

"Datos" tiene tanto la clave de datos cifrados como la clave de datos de texto sin formato como almacenamientos intermedios.

El siguiente paso es encriptar los datos con la clave de datos de texto sin formato.

http://docs.aws.amazon.com

A continuación se muestra un código de ejemplo que utiliza AES-CBC para cifrar datos utilizando la clave de datos. Esto usa el paquete crypto. Aquí he usado un iv fijo (vector de inicialización) para la simplicidad.

 función encryptAES (key, buffer) { 
const algorithm = 'AES-256-CBC';

const iv = new Buffer ('00000000000000000000000000000000', 'hex');

encryptor = crypto.createCipheriv (algoritmo, clave, iv);
encryptor.write (strBuffer);
encryptor.end ();

return encryptor.read ();
}

Veamos cómo descifrar los datos encriptados. En primer lugar, debemos descifrar nuestra clave eclipsada utilizando el CMK. El siguiente diagrama ilustra eso. El fragmento de código que publiqué anteriormente se puede usar para hacer esto (al igual que el descifrado de datos normal).

http://docs.aws.amazon.com

El último paso es descifrar los datos. El siguiente diagrama ilustra eso.

http://docs.aws.amazon.com

A continuación, se muestra un código de muestra para descifrar los datos que ciframos anteriormente utilizando AES-CBC.

 función decryptAES (clave, buffer) { 
const algorithm = 'AES-256-CBC';

const iv = new Buffer ('00000000000000000000000000000000', 'hex');

encryptor = crypto.createDecipheriv (algoritmo, clave, iv);
encryptor.write (buffer);
encryptor.end ();

return encryptor.read ();
}

Lo que sigue es un fragmento de código para encriptar y desencriptar una cadena usando encriptación de sobre.

 generateDataKey () 
.then (data => {
const cipherTextBlob = encryptAES (data.Plaintext, new Buffer ('abc', 'utf-8'));
for ( let i = 0; i <data.Plaintext.length; i ++) {
data.Plaintext [i] = null ;
}
descifrar (data.CiphertextBlob)
.then (clave => {
const dataBuffer = descifrar AES (clave, cifradoTextBlob);
console.log (dataBuffer.toString ('utf-8'));
});
});

Contexto de encriptación

Además de todo esto, AWS KMS brinda soporte para el contexto de encriptación para mejorar aún más la seguridad. Hay algunos problemas de seguridad que pueden mitigarse mediante el uso de un contexto de cifrado. Para obtener más información sobre el contexto de encriptación y cómo usarlo, diríjase aquí .

OK, estamos en el final. Este ha sido un artículo bastante largo. Pero espero que hayas aprendido algo de esto. ¡Ahora es el momento de comprobar AWS KMS!