Datos considerados a encriptar
- Todo lo que se considera confidencial para las organizaciones, sus empleados y sus clientes
- Numero de tarjetas de crédito
- Información personal
- Información de los salarios
- Información sobre la salud
- Número de cuentas bancarias
- Número de licencia de conducir
- Datos financieros
- La encriptación es el proceso de transformar un texto plano (plain text) en un texto cifrado (cipher text)
- La encriptación esconde el verdadero significado del mensaje pero no el mensaje en sí
- AES es uno de los algoritmos más populares usados en criptografía simétrica
Los servicios de seguridad siempre se presentan como la mayor amenazay han crecido de forma importante en los recientes años. Las empresas deben cumplir con las regulaciones de la industria y con el gobierno para asegurar la integridad de la información como los mencionados anteriormente. Para tal propósito la encriptación de datos es indispensable.
En DB2 para i 7.1 provee conocida como field procedure para enviar
Un field procedure es una rutina de salida escrito por el usuario diseñado para transformar los valores en una sola columna. Cuando se cambian los valores de la columna, o se insertan nuevos valores, el field procedure se invoca para cada valor de y puede transformar ese valor (codificar) en cualquier forma, y luego lo almacena.
Cuando los valores se recuperan de la columna, el field procedure se invoca para cada valor codificado, que entonces decodifica de nuevo al valor original. Cualquier índices definidos en una columna no derivada que utiliza un procedimiento de campo se construyen con valores codificados.
- Asegure cifrado: Los datos, índices y revistas almacenadas en discos duros o cintas son una versión transformada (encriptada) de los datos. No se pueden obtener los datos descifrados sin el programa FieldProc.
- Uso fácil : Para activar el field procedure, sólo tiene que escribir un programa FieldProc (o llamar a funciones de cifrado / descifrado de terceros) y luego registrarlo en la tabla.
- Más flexibilidad :Se puede cambiar fácilmente a otros métodos de cifrado mediante la adición, dejar caer o moverse a otros programas FieldProc. Tenga en cuenta que a pesar de que un valor codificado puede ser más largo que el valor definido del campo, que es flexible y se puede cambiar con los programas FieldProc. No se necesita ningún cambio en la definición de la tabla inicial.
Create TABLE employee ( ID char(10), salary decimal(10,2) FieldProc FP.userpgm ) |
O una tabla de empleados existente puede ser modificado para encriptar los datos sensibles de salario columna:
ALTER TABLE employee alter column salary set FieldProc FP.userpgm //We can alter to add a FieldProc on both SQL table and Native table. |
Por supuesto, el procedimiento de campo también se puede quitar, y se puede utilizar otro procedimiento de campo para encriptar los datos sensibles:
ALTER TABLE FP.userpgm alter column salary drop FieldProc // drop the old field procedure ALTER TABLE employee alter column salary set FieldProc FP.userpgm2 //then add the new one |
- En el caso del campo de definición, cuando se ejecuta la sentencia CREATE TABLE o ALTER TABLE que da nombre al procedimiento. Durante esta invocación, se prevé que el procedimiento para determinar la validez de los tipos de datos y atributos de la columna, verifique la lista literal, y proporcionar la descripción del campo de la columna.
- En el caso de codificación de campo, cuando un valor de columna es para ser codificada en campo. Esto ocurre para cualquier valor que se inserta en un SQL INSERT o MERGE, para una escritura nativa, se cambia por actualización o se copian los datos a una columna de destino con un field procedure registrado.
- En el caso de campo-decodificación, cuando un valor almacenado es ser campo-decodificado de nuevo a su valor original. Esto ocurre para cualquier valor que se recupera de una SQL SELECT o FETCH declaración, por una lectura nativa, o los datos se copian a una columna de destino sin un procedimiento de campo registrados.
Este ejemplo muestra cómo utilizar programas de cifrado / descifrado, o funciones de cifrado / descifrado de terceros para realizar el cifrado. El programa de cifra y descifra una cadena de caracteres 16 que sólo incluye números.
#include <ctype.h> #include <string.h> #include <stdlib.h> #include <SQLFP.h> void DESC(unsigned char *data, unsigned char *mkey, char ctag[2]) { ... //user created or third party encryption algorithm. } main(int argc, void *argv[]) { short *funccode = argv[1]; sqlfpFieldProcedureParameterList_T *optionalParms = argv[2]; char *sqlstate = argv[7]; sqlfpMessageText_T *msgtext = argv[8]; sqlfpOptionalParameterValueDescriptor_T *optionalParmPtr; char KEY[16]="0123456789ABCDEF"; if (*funccode == 8) /* create time */ { sqlfpParameterDescription_T *inDataType = argv[3]; sqlfpParameterDescription_T *outDataType = argv[5]; if (inDataType->sqlfpSqlType !=452 && inDataType->sqlfpSqlType !=453 ) /* only support fixed length */ memcpy(sqlstate,"38002",5); /* do something here to determine the result data type */ /* ..... */ /* in this example input and output types are exactly the same */ /* so just copy */ memcpy(outDataType, inDataType, sizeof(sqlfpParameterDescription_T)); } else if (*funccode == 0) /* encode */ { memcpy((char *)argv[6], (char *)argv[4], 16); DESC((char*)argv[6], KEY, "0"); } else if (*funccode == 4) /* decode */ { memcpy((char *)argv[4], (char *)argv[6], 16); memcpy((char *)argv[4], (char *)argv[6], 16); DESC((char *)argv[4], KEY, "1"); } else /* unsupported option -- error */ memcpy(sqlstate, "38003",5); } |
<!-- In this example, there are some points which need attention: --> <!-- a. The input/output data type could be a fixed char or varchar or clob. --> <!-- But the block size of the encryption should be 16x(multiple time of 16).--> <!-- So, we should define enough space to store the encryption result. --> <!-- b. Avoid using pad option. Pad option will add a count of the pad characters --> <!-- in the end of original string.--> <!-- It may conduct one more block of the encryption result and the --> <!-- column does not have enough space to store. --> <!-- c. For better performance, ACTGRP(*CALLER), TERASPACE(*YES) and STGMDL(*INHERIT)--> <!-- were recommended when you compile your program.--> <!-- d. More information about IBM i Cryptographic Services APIs, --> <!-- please refer to the link of the IBM i infocenter below:--> <!-- http://publib.boulder.ibm.com/infocenter/iseries/7.1m0/index.jsp --> #include <string.h> #include <stdlib.h> #include <stdio.h> #include <QC3CCI.H> #include <QUSEC.H> #include <QC3DTAEN.H> #include <QC3DTADE.H> #include <SQLFP.h> <!-- --------------------- --> <!-- SQL data type define. --> <!-- --------------------- --> <!-- SQL data type CLOB --> #define SQL_CLOB_1 408 #define SQL_CLOB_2 409 <!-- SQL data type VARCHAR --> #define SQL_VARCHAR_1 448 #define SQL_VARCHAR_2 449 <!-- SQL data type CHAR --> #define SQL_CHAR_1 452 #define SQL_CHAR_2 453 <!-- ------------------------------ --> <!-- Varlength SQL data type define. --> <!-- ------------------------------ --> typedef _Packed struct { unsigned short int len; char data[512]; }T_VARCHAR; typedef _Packed struct { unsigned long len; char data[512]; }T_CLOB; Qc3_Format_ALGD0200_T *ALGD0200; Qc3_Format_KEYD0200_T *KEYD0200; Qus_EC_t ERRCODE; main(int argc, void *argv[]) { T_VARCHAR VarCharStr; T_CLOB ClobStr; short *funccode = argv[1]; sqlfpFieldProcedureParameterList_T *optionalParms = argv[2]; char *sqlstate = argv[7]; sqlfpMessageText_T *msgtext = argv[8]; sqlfpOptionalParameterValueDescriptor_T *optionalParmPtr; char Clear_Data[512]; char Encrypted_Data[512]; char Decrypted_Data[512]; int InputDataLen; int EncryptedDataLen; int DecryptedDataLen; int RtnLen; int i; char Qc3_Any_CSP_Flag = Qc3_Any_CSP; ALGD0200 = (Qc3_Format_ALGD0200_T *)malloc(sizeof(Qc3_Format_ALGD0200_T)); ALGD0200->Block_Cipher_Alg = Qc3_AES; ALGD0200->Block_Length = 16; ALGD0200->Mode = Qc3_ECB; ALGD0200->Pad_Option = Qc3_No_Pad; ALGD0200->Pad_Character = '\x00' ; ALGD0200->MAC_Length = 0; ALGD0200->Effective_Key_Size = 0; ALGD0200->Reserved = '\x00'; memset(ALGD0200->Init_Vector,'\x00',32); KEYD0200 = (Qc3_Format_KEYD0200_T *)malloc(sizeof(Qc3_Format_KEYD0200_T) +16); KEYD0200->Key_Type = Qc3_AES ; KEYD0200->Key_String_Len = 16; KEYD0200->Key_Format = Qc3_Bin_String; memcpy((char *)KEYD0200->Reserved + 3, "0123456789ABCDEF", 16); if (*funccode == 8) /* create time */ { sqlfpParameterDescription_T *inDataType = argv[3]; sqlfpParameterDescription_T *outDataType = argv[5]; /* do something here to determine the result data type */ /* ..... */ /* in this example input and output types are exactly the same */ /* so just copy */ memcpy(outDataType, inDataType, sizeof(sqlfpParameterDescription_T)); } else if (*funccode == 0) /* encode */ { sqlfpParameterDescription_T *inDataType = argv[3]; InputDataLen = inDataType->sqlfpByteLength; if (inDataType->sqlfpSqlType == SQL_VARCHAR_1 || inDataType->sqlfpSqlType == SQL_VARCHAR_2) { memcpy((char *)&VarCharStr, (char *)argv[4], InputDataLen+2); InputDataLen = VarCharStr.len; memcpy((char *)Clear_Data, (char *)VarCharStr.data, InputDataLen); if (InputDataLen % 16 > 0 || InputDataLen == 0) { memset((char *)Clear_Data + InputDataLen, '\x00', 16 - InputDataLen % 16); InputDataLen = ((int)(InputDataLen / 16) + 1) * 16; } } else if (inDataType->sqlfpSqlType == SQL_CLOB_1 || inDataType->sqlfpSqlType == SQL_CLOB_2) { memcpy((char *)&ClobStr, (char *)argv[4], InputDataLen+4); InputDataLen = ClobStr.len; memcpy((char *)Clear_Data, (char *)ClobStr.data, InputDataLen); if (InputDataLen % 16 > 0 || InputDataLen == 0) { memset((char *)Clear_Data + InputDataLen, '\x00', 16 - InputDataLen % 16); InputDataLen = ((int)(InputDataLen / 16) + 1) * 16; } } else memcpy((char *)Clear_Data, (char *)argv[4], InputDataLen); memset(Encrypted_Data,'\x00',sizeof(Encrypted_Data)); EncryptedDataLen = sizeof(Encrypted_Data); Qc3EncryptData(Clear_Data, &InputDataLen, Qc3_Data, (char *)ALGD0200, Qc3_Alg_Block_Cipher, (char *)KEYD0200, Qc3_Key_Parms, &Qc3_Any_CSP_Flag, " ", Encrypted_Data, &EncryptedDataLen, &RtnLen, &ERRCODE); if (inDataType->sqlfpSqlType == SQL_VARCHAR_1 || inDataType->sqlfpSqlType == SQL_VARCHAR_2) { VarCharStr.len = RtnLen; memcpy((char *)VarCharStr.data, (char *)Encrypted_Data, RtnLen); memcpy((char *)argv[6], (char *)&VarCharStr, RtnLen+2); } else if (inDataType->sqlfpSqlType == SQL_CLOB_1 || inDataType->sqlfpSqlType == SQL_CLOB_2) { ClobStr.len = RtnLen; memcpy((char *)ClobStr.data, (char *)Encrypted_Data, RtnLen); memcpy((char *)argv[6], (char *)&ClobStr, RtnLen+4); } else memcpy((char *)argv[6], (char *)Encrypted_Data, RtnLen); } else if (*funccode == 4) /* decode */ { sqlfpParameterDescription_T *inDataType = argv[3]; InputDataLen = inDataType->sqlfpByteLength; if (inDataType->sqlfpSqlType == SQL_VARCHAR_1 || inDataType->sqlfpSqlType == SQL_VARCHAR_2) { memcpy((char *)&VarCharStr, (char *)argv[6], InputDataLen+2); InputDataLen = VarCharStr.len; memcpy((char *)Encrypted_Data, (char *)VarCharStr.data, InputDataLen); } else if (inDataType->sqlfpSqlType == SQL_CLOB_1 || inDataType->sqlfpSqlType == SQL_CLOB_2) { memcpy((char *)&ClobStr, (char *)argv[6], InputDataLen+4); InputDataLen = ClobStr.len; memcpy((char *)Encrypted_Data, (char *)ClobStr.data, InputDataLen); } else memcpy((char *)Encrypted_Data, (char *)argv[6], InputDataLen); memset(Decrypted_Data,'\x00',sizeof(Decrypted_Data)); DecryptedDataLen = sizeof(Decrypted_Data); Qc3DecryptData(Encrypted_Data, &InputDataLen, (char *)ALGD0200, Qc3_Alg_Block_Cipher, (char *)KEYD0200, Qc3_Key_Parms, &Qc3_Any_CSP_Flag, " ", Decrypted_Data, &DecryptedDataLen, &RtnLen, &ERRCODE); if (inDataType->sqlfpSqlType == SQL_VARCHAR_1 || inDataType->sqlfpSqlType == SQL_VARCHAR_2) { VarCharStr.len = strlen(Decrypted_Data); memcpy((char *)VarCharStr.data, (char *)Decrypted_Data, VarCharStr.len); memcpy((char *)argv[4], (char *)&VarCharStr, VarCharStr.len+2); } else if (inDataType->sqlfpSqlType == SQL_CLOB_1 || inDataType->sqlfpSqlType == SQL_CLOB_2) { ClobStr.len = strlen(Decrypted_Data); memcpy((char *)ClobStr.data, (char *)Decrypted_Data, ClobStr.len); memcpy((char *)argv[4], (char *)&ClobStr, ClobStr.len+4); } else memcpy((char *)argv[4], (char *)Decrypted_Data, RtnLen); } else /* unsupported option -- error */ memcpy(sqlstate, "38003",5); } |
D FuncCode S 2B 0 D p_FuncCode S * D OptParms DS LikeDs(SQLFOPVD) D* D EnCodTyp DS LikeDs(SQLFPD) D* D DeCodTyp DS LikeDs(SQLFPD) D* D EnCodDta S 512 D DeCodDta S 512 D* D SqlState S 5 D SqMsgTxt DS LikeDs(SQLFMT) D* D En_Lob_Ds Ds Qualified D Len 5B 0 D Data 1 dim(512) D D De_Lob_Ds Ds LikeDs(En_Lob_Ds) D D En_VChar_Ds Ds Qualified D Len 2B 0 D Data 1 dim(512) D D De_VChar_Ds Ds LikeDs(En_VChar_Ds) D D i S 10I 0 D /COPY QSYSINC/QRPGLESRC,SQLFP C *Entry Plist C Parm FuncCode C Parm OptParms C Parm DeCodTyp C Parm DeCodDta C Parm EnCodTyp C Parm EnCodDta C Parm SqlState C Parm SqMsgTxt /Free If FuncCode = 8 ; // do something here to determine the result data type // ..... // in this example input and output types are exactly the same // so just copy EnCodTyp = DeCodTyp ; ElseIf FuncCode = 0 ; // encode If DeCodTyp.SQLFST = 408 or DeCodTyp.SQLFST = 409 ; // clob // in this example, reverse the characters as encryption De_Lob_Ds = DeCodDta ; En_Lob_Ds.Len = De_Lob_Ds.Len ; i = De_Lob_Ds.Len ; DoW i > 0 ; En_Lob_Ds.Data(De_Lob_Ds.Len-i+1) = De_Lob_Ds.Data(i) ; i = i - 1 ; EndDo ; EnCodDta = En_Lob_Ds ; ElseIf DeCodTyp.SQLFST = 448 or DeCodTyp.SQLFST = 449 ; // varchar // in this example, reverse the characters as encryption De_VChar_Ds = DeCodDta ; En_VChar_Ds.Len = De_VChar_Ds.Len ; i = De_VChar_Ds.Len ; DoW i > 0 ; En_VChar_Ds.Data(De_VChar_Ds.Len-i+1) = De_VChar_Ds.Data(i) ; i = i - 1 ; EndDo ; EnCodDta = En_VChar_Ds ; Else ; // other data type, just put the same value. EnCodDta = DeCodDta ; EndIf ; SqlState = '00000' ; ElseIf FuncCode = 4 ; // decode If EnCodTyp.SQLFST = 408 or EnCodTyp.SQLFST = 409 ; // clob // in this example, reverse the characters as decryption En_Lob_Ds = EnCodDta ; De_Lob_Ds.Len = En_Lob_Ds.Len ; i = En_Lob_Ds.Len ; DoW i > 0 ; De_Lob_Ds.Data(En_Lob_Ds.Len-i+1) = En_Lob_Ds.Data(i) ; i = i - 1 ; EndDo ; DeCodDta = De_Lob_Ds ; ElseIf EnCodTyp.SQLFST = 448 or EnCodTyp.SQLFST = 449 ; // varchar En_VChar_Ds = EnCodDta ; De_VChar_Ds.Len = En_VChar_Ds.Len ; i = En_VChar_Ds.Len ; DoW i > 0 ; De_VChar_Ds.Data(En_VChar_Ds.Len-i+1) = En_VChar_Ds.Data(i) ; i = i - 1 ; EndDo ; DeCodDta = De_VChar_Ds ; Else ; // other data type, just put the same value. DeCodDta = EnCodDta ; EndIf ; SqlState = '00000' ; Else ; SqlState = '38003' ; EndIf ; *InLR = *On ; Return ; /End-Free |
.
Existen varias pautas que se deben tener en cuenta al adoptar apoyo procedimiento campo. Los elementos clave incluyen:- El procedimiento de campo debe ser un objeto * PGM ILE. Tenga en cuenta que * SRVPGMs, OPM * PGM y objetos Java no son compatibles.
- No se permite SQL en un procedimiento de campo.
- El procedimiento de campo debe ser determinista. Es muy peligroso utilizar los procedimientos de campo que no son deterministas porque los datos codificados pueden no ser capaces de decodificar de nuevo a su valor original.
- Cuando se utiliza el comando de archivo físico Change (CHGPF) con el parámetro SRCFILE para cambiar la definición de campo de un archivo físico, el comando CHGPF eliminará todos los procedimientos de campo registrados en el archivo físico sin ningún mensaje de advertencia.
Con la utilización delfield procedure, se puede realizar fácilmente un cifrado transparente de nivel de columna de los datos almacenados en una base de datos. Usted puede utilizar FieldProc para cualquier tipo de esquema de codificación.
Como le puedo pasar un parametro a un programa que se llama desde el fieldproc ????
ResponderBorrarALTER TABLE sistemdb/client1 ALTER COLUMN CLI_TCHCOR
SET FIELDPROC sistempgm/PROGRAMA PARM('001' '123456' ' ' ' ')
DONDE PARM SON LOS PARÁMETROS PERO NO FUNCIONA LA CENETENCIA CON ESTA INSTRUCCIÓN (PARM) ?????