Almacenar de forma segura los detalles de la cuenta bancaria en la base de datos

5

Estoy desarrollando un servicio que incluirá el débito directo de las cuentas de los clientes de forma rutinaria (semanal, mensual, etc.), por lo que necesitaré almacenar su información (BSB / número de ruta y número de cuenta) en mi base de datos Estoy muy preocupado por la seguridad, por lo que mi primer pensamiento fue no almacenar esta información, pero después de leer muchas otras preguntas sobre este tema, se me ocurrió una solución que creo que funcionará, pero me gustaría hacerla funcionar. Más allá de ustedes, asegúrese de que no haya dejado ningún agujero de seguridad abierto.

Cuando un usuario se registra en el servicio, creará un par de claves pública / privada con la clave privada que tiene una frase de contraseña que proporciona el usuario (la contraseña de su cuenta). La contraseña se oculta con bcrypt y las claves pública y privada se almacenan junto con el hash de contraseña en la tabla de usuarios.

También estableceré un único par de claves públicas / privadas que se utilizarán cuando necesitemos procesar un débito directo. La aplicación y la base de datos conocerán la clave pública, pero la clave privada se mantendrá fuera del servidor, de modo que los datos solo podrán descargarse cuando estén cifrados y luego procesados en otro lugar. Una alternativa a la descarga cuando está cifrada sería, en cambio, cargar la clave privada a la aplicación, descifrar los datos solo para esa solicitud y luego eliminar la clave privada cargada. ¿Es esto un agujero de seguridad?

Cuando un usuario se registra para débito directo, el servicio tomará la clave pública del usuario y la clave pública del administrador, y las cifrará usando función de múltiples destinatarios de GPG .

Según mi conocimiento, esto cubre las siguientes situaciones:

  • Si el usuario desea ver los datos, deberá proporcionar su contraseña para descifrar la información.
  • Si el usuario desea agregar más datos, no tendrá que proporcionar su contraseña, ya que solo uso su clave pública.
  • Si el administrador desea ver los datos, deberá descargar la información y descifrarla, o bien cargar su clave privada (ver más arriba).
  • Si el usuario cambia su contraseña, solo necesitaré actualizar su clave privada. Si han olvidado su contraseña, la única forma en que podría descifrar sus datos sería a través de la clave privada del administrador, pero como esta se mantiene fuera del sitio, los datos deben eliminarse.

¿Habrá alguna preocupación si el par de claves de administración alguna vez se comprometa (aparte de lo obvio) y necesito generar un nuevo par de claves de administración y luego volver a cifrar todos los datos almacenados?

¿Hay agujeros de seguridad en este diseño? Reconozco que no soy un experto, pero he intentado hacer mi mejor esfuerzo investigando esto, y ahora me encantaría recibir alguna información.

También he consultado servicios como Gerente de Información del Cliente (CIM) de Authorize.net pero hasta donde llego puede ver que necesita utilizar su servicio para cobrar los pagos, cuando en cambio ya hemos establecido nuestro propio comerciante para que lo haga a una tarifa más barata, por lo que solo necesitamos un servicio de almacenamiento de información seguro.

El servicio utilizará HTTPS y se ejecutará en Ubuntu 12.04, con PHP y MySQL, si eso ayuda.

¡Cualquier consejo que puedas dar será muy apreciado!

Gracias

    
pregunta mitchdav 01.07.2015 - 03:45
fuente

3 respuestas

4
  

La contraseña está codificada con bcrypt, y las claves pública y privada   se almacenan junto con el hash de contraseña en la tabla de usuario.

El almacenamiento de la clave privada significa que un compromiso de la base de datos permitiría al atacante descifrar la información del banco. También puede almacenar la información bancaria en texto sin formato.

¿Por qué exactamente la información del banco tendría que estar encriptada por la clave del usuario de todos modos? ¿El usuario va a solicitar esa información "por favor, dígame la cuenta bancaria que le mencioné anteriormente"?

    
respondido por el Gerald Davis 01.07.2015 - 03:51
fuente
2

Le recomiendo que considere seriamente pagarle a un tercero por la seguridad, ya que probablemente sea la solución más fiscalmente responsable. Si maneja usted mismo los datos de la tarjeta de pago, será responsable de las auditorías de PCI, que pueden ser muy costosas. Y después del próximo cambio de responsabilidad de octubre de 2015 (suponiendo que se encuentre en los EE. UU.), El eslabón más débil de la cadena de pago será responsable de cubrir los gastos de fraude. Si sus sistemas no funcionan, no hay duda de que los bancos, sus procesadores de pagos y las víctimas se quedarán sin trabajo. ¿Tendría el dinero para cubrir ese tipo de pérdidas?

    
respondido por el John Deters 01.07.2015 - 03:59
fuente
0

Sí, use estas funciones para cifrar & descifrar los datos de la base de datos.

  static function encrypt($s) {
    $keyHex = getenv('APP_KEY');
    if (!$keyHex) {
      Yii::error ("Could not retrieve environment variable APP_KEY");
      return null;
    }
    $key = pack('H*', $keyHex); 
    $iv = mcrypt_create_iv(256/8); // 256 bit / 8 bit/byte = 32
    $cipherText = mcrypt_encrypt(MCRYPT_RIJNDAEL_256, $key, $s, 'cbc', $iv);
    $cipherText64 = base64_encode($iv.$cipherText);
    return $cipherText64;
  }

  static function decrypt($s) {
    $keyHex = getenv('APP_KEY');
    if (!$keyHex) {
      Yii::error ("Could not retrieve environment variable APP_KEY");
      return null;
    }
    $key = pack('H*', $keyHex);
    $cipher = base64_decode($s); 
    $iv = substr($cipher, 0, 256/8);
    $cipher = substr($cipher, 256/8); // strip off IV from front
    $text = mcrypt_decrypt(MCRYPT_RIJNDAEL_256, $key, $cipher, "cbc", $iv);
    $text = rtrim($text, "
  static function encrypt($s) {
    $keyHex = getenv('APP_KEY');
    if (!$keyHex) {
      Yii::error ("Could not retrieve environment variable APP_KEY");
      return null;
    }
    $key = pack('H*', $keyHex); 
    $iv = mcrypt_create_iv(256/8); // 256 bit / 8 bit/byte = 32
    $cipherText = mcrypt_encrypt(MCRYPT_RIJNDAEL_256, $key, $s, 'cbc', $iv);
    $cipherText64 = base64_encode($iv.$cipherText);
    return $cipherText64;
  }

  static function decrypt($s) {
    $keyHex = getenv('APP_KEY');
    if (!$keyHex) {
      Yii::error ("Could not retrieve environment variable APP_KEY");
      return null;
    }
    $key = pack('H*', $keyHex);
    $cipher = base64_decode($s); 
    $iv = substr($cipher, 0, 256/8);
    $cipher = substr($cipher, 256/8); // strip off IV from front
    $text = mcrypt_decrypt(MCRYPT_RIJNDAEL_256, $key, $cipher, "cbc", $iv);
    $text = rtrim($text, "%pre%"); // mcrypt leaves null padding on the text
    return $text;
  }
"); // mcrypt leaves null padding on the text return $text; }

Actualmente obtienen la clave de una variable de entorno, por lo que tendrá que modificarla para obtener la clave del usuario. Supongo que querrá que el usuario escriba la contraseña en cada & Cada vez que acceden a sus datos bancarios. No tienes que usar cifrado público / privado. Eso solo es bueno para valores pequeños, pero los números de cuentas bancarias son probablemente lo suficientemente pequeños. La clave debe ser una cadena hexadecimal de 64 caracteres, una clave de 32 bytes o una clave de 256 bits. Sin embargo, tiene que ser seguro al azar. Si permite que el usuario proporcione una contraseña y la convierta en una clave con una función de derivación de clave basada en contraseña (PBKDF), entonces alguien podría atacar la base de datos con fuerza bruta.

    
respondido por el Chloe 01.07.2015 - 06:46
fuente

Lea otras preguntas en las etiquetas