Seudonimización

Descripción general del concepto

La seudonimización (también conocida como asignación de tokens) es una técnica de desidentificación en la que los datos sensibles se reemplazan con subrogados (o tokens) de una manera coherente. La diferencia con otras técnicas de desidentificación, como el ocultamiento o la generalización, es que los subrogados retienen sus propiedades referenciales dentro del conjunto de datos desidentificado. Además, un usuario autorizado puede revertir estos subrogados a sus valores sensibles originales, dependiendo de la transformación con que se produjeron.

Ejemplo de transformación

Ten en cuenta el siguiente ejemplo para comprender la utilidad de la seudonimización.

Supongamos que tenemos los siguientes datos:

ID de empleado Fecha Compensación
11111 2015 $10
11111 2016 $20
22222 2016 $15

Tal vez queramos saber cómo cambió la compensación de los empleados con el tiempo para identificar a los que tienen valores atípicos. Si encontramos uno de estos valores, debemos corregir la diferencia de los ingresos. Además, nuestro objetivo sería hacerlo sin exponer los datos de compensación sensibles de alguno de los individuos.

Si suponemos que la única manera de identificar a los empleados es mediante la columna “ID de empleado”, esta se debe desidentificar.

A partir de allí, podemos aplicar una transformación de seudonimización a “ID de empleado”. Considera dos opciones para las transformaciones de seudonimización: CryptoHashConfig y CryptoReplaceFfxFpeConfig. Tendremos que usar una transformación reversible, puesto que queremos ser capaces de recuperar al empleado con el valor atípico. Eso limita nuestra selección a CryptoReplaceFfxFpeConfig.

El siguiente paso es configurar la transformación de la siguiente manera:

"cryptoReplaceFfxFpeConfig": {
  "cryptoKey": {
    "unwrapped": {
      "key": "YWJjZGVmZ2hpamtsbW5vcA=="
    }
  },
  "commonAlphabet": "NUMERIC"
}

Aplicamos esta transformación a “ID de empleado” a través del método content.deidentify de la siguiente manera:

Entrada de JSON:

POST https://dlp.googleapis.com/v2/projects/[PROJECT_ID]/content:deidentify?key={YOUR_API_KEY}

{
  "deidentifyConfig":{
    "recordTransformations":{
      "fieldTransformations":[
        {
          "primitiveTransformation":{
            "cryptoReplaceFfxFpeConfig":{
              "cryptoKey":{
                "unwrapped":{
                  "key":"YWJjZGVmZ2hpamtsbW5vcA=="
                }
              },
              "commonAlphabet":"NUMERIC"
            }
          },
          "fields":[
            {
              "name":"Employee ID"
            }
          ]
        }
      ]
    }
  },
  "item":{
    "table":{
      "headers":[
        {
          "name":"Employee ID"
        },
        {
          "name":"Date"
        },
        {
          "name":"Compensation"
        }
      ],
      "rows":[
        {
          "values":[
            {
              "stringValue":"11111"
            },
            {
              "stringValue":"2015"
            },
            {
              "stringValue":"$10"
            }
          ]
        },
        {
          "values":[
            {
              "stringValue":"11111"
            },
            {
              "stringValue":"2016"
            },
            {
              "stringValue":"$20"
            }
          ]
        },
        {
          "values":[
            {
              "stringValue":"22222"
            },
            {
              "stringValue":"2016"
            },
            {
              "stringValue":"$15"
            }
          ]
        }
      ]
    }
  }
}

Salida de JSON:

{
  "item":{
    "table":{
      "headers":[
        {
          "name":"Employee ID"
        },
        {
          "name":"Date"
        },
        {
          "name":"Compensation"
        }
      ],
      "rows":[
        {
          "values":[
            {
              "stringValue":"28777"
            },
            {
              "stringValue":"2015"
            },
            {
              "stringValue":"$10"
            }
          ]
        },
        {
          "values":[
            {
              "stringValue":"28777"
            },
            {
              "stringValue":"2016"
            },
            {
              "stringValue":"$20"
            }
          ]
        },
        {
          "values":[
            {
              "stringValue":"39344"
            },
            {
              "stringValue":"2016"
            },
            {
              "stringValue":"$15"
            }
          ]
        }
      ]
    }
  },
  "overview":{
    "transformedBytes":"15",
    "transformationSummaries":[
      {
        "field":{
          "name":"Employee ID"
        },
        "results":[
          {
            "count":"3",
            "code":"SUCCESS"
          }
        ],
        "fieldTransformations":[
          {
            "fields":[
              {
                "name":"Employee ID"
              }
            ],
            "primitiveTransformation":{
              "cryptoReplaceFfxFpeConfig":{
                "cryptoKey":{
                  "unwrapped":{
                    "key":"YWJjZGVmZ2hpamtsbW5vcA=="
                  }
                },
                "commonAlphabet":"NUMERIC"
              }
            }
          }
        ],
        "transformedBytes":"15"
      }
    ]
  }
}

Después de la transformación, la tabla se verá de la siguiente forma:

ID de empleado Fecha Compensación
28777 2015 $10
28777 2016 $20
39344 2016 $15

Esta transformación se adapta a nuestras necesidades, puesto que quita el ID real del empleado y reemplaza los ID idénticos de manera coherente, para que los registros de un empleado específico sigan vinculados. Por ejemplo, el ID de empleado “11111” se reemplazó coherentemente con “28777” en los dos primeros registros. De esta manera, se mantiene el valor de análisis de los datos resultantes, al igual que la privacidad.

Ejemplo de reversión

Retomaremos el ejemplo anterior para explicar la reversión. Supongamos que, gracias al análisis, se determina que al empleado con el ID “28777” se le debió pagar un salario más alto y, debido a esto, los propietarios de los datos (como los administradores de la empresa) deben ajustar su compensación. Para ello, necesitarán el ID de empleado real. Para revertir “28777” al ID real, usamos el método content.reidentify como se muestra en el siguiente ejemplo de JSON:

Entrada de JSON:

POST https://dlp.googleapis.com/v2/projects/[PROJECT_ID]/content:reidentify?key={YOUR_API_KEY}

{
  "reidentifyConfig":{
    "recordTransformations":{
      "fieldTransformations":[
        {
          "primitiveTransformation":{
            "cryptoReplaceFfxFpeConfig":{
              "cryptoKey":{
                "unwrapped":{
                  "key":"YWJjZGVmZ2hpamtsbW5vcA=="
                }
              },
              "commonAlphabet":"NUMERIC"
            }
          },
          "fields":[
            {
              "name":"Employee ID"
            }
          ]
        }
      ]
    }
  },
  "item":{
    "table":{
      "headers":[
        {
          "name":"Employee ID"
        }
      ],
      "rows":[
        {
          "values":[
            {
              "stringValue":"28777"
            }
          ]
        }
      ]
    }
  }
}

Salida de JSON:

{
  "item":{
    "table":{
      "headers":[
        {
          "name":"Employee ID"
        }
      ],
      "rows":[
        {
          "values":[
            {
              "stringValue":"11111"
            }
          ]
        }
      ]
    }
  },
  "overview":{
    "transformedBytes":"5",
    "transformationSummaries":[
      {
        "field":{
          "name":"Employee ID"
        },
        "results":[
          {
            "count":"1",
            "code":"SUCCESS"
          }
        ],
        "fieldTransformations":[
          {
            "fields":[
              {
                "name":"Employee ID"
              }
            ],
            "primitiveTransformation":{
              "cryptoReplaceFfxFpeConfig":{
                "cryptoKey":{
                  "unwrapped":{
                    "key":"YWJjZGVmZ2hpamtsbW5vcA=="
                  }
                },
                "commonAlphabet":"NUMERIC"
              }
            }
          }
        ],
        "transformedBytes":"5"
      }
    ]
  }
}

Como aparece en la salida de JSON, el resultado que se muestra es el ID real del empleado: “11111”.

Contextos

Cuando se transforman datos estructurados (datos tabulares con registros y campos) con una transformación de seudonimización, como CryptoReplaceFfxFpeConfig, se puede especificar un context. Cuando se especifica, context define un campo cuyo valor en un registro determinado se tomará como “ajuste”. Por ejemplo, en la tabla que aparece a continuación, se puede elegir “ID de paciente” como contexto, en cuyo caso el ajuste se toma como “4672” para el primer registro, “3246” para el segundo registro, y así sucesivamente.

En primer lugar, para comprender el propósito de especificar un contexto, supongamos que el campo “Nombre” de la tabla se transformará sin usar un contexto. En este caso, cada nombre idéntico se reemplazará con el mismo token. Esto quiere decir que dos tokens coincidentes hacen referencia al mismo nombre. Sin embargo, es posible que no se quiera mostrar esta conexión, ya que podría revelar relaciones sensibles entre los registros. En estas situaciones, podemos usar un contexto para deshacer estas relaciones, en cuyo caso solo se conservarán en los tokens que se generaron mediante una alteración idéntica.

Por ejemplo, consideremos la siguiente tabla:

Número de factura ID de paciente Nombre
223 4672 José  
224 3246 Débora  
225 3529 Nicolás  
226 4098 Débora  
     

Aplicar esta transformación a “Nombre” sin especificar un contexto da como resultado la siguiente tabla transformada (los valores de token exactos dependen del cryptoKey especificado):

Número de factura ID de paciente Nombre
223 4672 gCUv  
224 3246 Eusyv  
225 3529 dsla  
226 4098 Eusyv  
     

Observa que, en la tabla anterior, los tokens de los registros de “Débora” son los mismos. Para deshacer la relación, podemos especificar “ID de paciente” como el contexto y ejecutar la transformación en la tabla original. Esto produce la siguiente tabla transformada (los valores de token exactos dependen del cryptoKey especificado):

Número de factura ID de paciente Nombre
223 4672 Agca  
224 3246 vSHig  
225 3529 kqHX  
226 4098 CUgv  
     

Observa cómo se reemplazó “Débora” con tokens diferentes, ya que el “ID de paciente” difería entre los dos registros.

Anotaciones de los subrogados

En los ejemplos anteriores, se usaron datos estructurados (tabulares). Esto facilita la reversión, ya que encontrar el token que se debe revertir es sencillo. Sin embargo, si el token se encuentra en texto libre, primero se debe encontrar para realizar la reversión. Las transformaciones reversibles lo permiten mediante el campo surrogateInfoType. Para obtener más información, consulta CryptoReplaceFfxFpeConfig.

Este campo funciona junto con el tipo de información personalizada SurrogateType para facilitar la inspección de tokens en el texto libre.

Ejemplo de desidentificación en código de texto libre

Considera el siguiente ejemplo: Estamos usando el método content.deidentify para transformar un número de teléfono que se encuentra en texto libre mediante un token.

Entrada de JSON:

POST https://dlp.googleapis.com/v2/projects/velvety-study-196101/content:deidentify?key={YOUR_API_KEY}

{
  "deidentifyConfig":{
    "infoTypeTransformations":{
      "transformations":[
        {
          "infoTypes":[
            {
              "name":"PHONE_NUMBER"
            }
          ],
          "primitiveTransformation":{
            "cryptoReplaceFfxFpeConfig":{
              "cryptoKey":{
                "unwrapped":{
                  "key":"YWJjZGVmZ2hpamtsbW5vcA=="
                }
              },
              "commonAlphabet":"NUMERIC",
              "surrogateInfoType":{
                "name":"PHONE_TOKEN"
              }
            }
          }
        }
      ]
    }
  },
  "inspectConfig":{
    "infoTypes":[
      {
        "name":"PHONE_NUMBER"
      }
    ],
    "minLikelihood":"UNLIKELY"
  },
  "item":{
    "value":"My phone number is 4359916732"
  }
}

Después de que JSON se envía a la URL especificada, Cloud DLP muestra el siguiente resultado.

Salida de JSON:

{
 "item": {
  "value": "My phone number is PHONE_TOKEN(10):9617256398"
 },
 "overview": {
  "transformedBytes": "10",
  "transformationSummaries": [
   {
    "infoType": {
     "name": "PHONE_NUMBER"
    },
    "transformation": {
     "cryptoReplaceFfxFpeConfig": {
      "cryptoKey": {
       "unwrapped": {
        "key": "YWJjZGVmZ2hpamtsbW5vcA=="
       }
      },
      "commonAlphabet": "NUMERIC",
      "surrogateInfoType": {
       "name": "PHONE_TOKEN"
      }
     }
    },
    "results": [
     {
      "count": "1",
      "code": "SUCCESS"
     }
    ],
    "transformedBytes": "10"
   }
  ]
 }
}

Cloud DLP desidentificó correctamente el número de teléfono (9617256398).

Ejemplo de reidentificación en código de texto libre

En este segundo ejemplo, usamos el método content.reidentify para revertir el texto transformado del primer ejemplo al número original.

Entrada de JSON:

POST https://dlp.googleapis.com/v2/projects/[PROJECT_ID]/content:reidentify?key={YOUR_API_KEY}

{
 "reidentifyConfig": {
  "infoTypeTransformations": {
   "transformations": [
    {
     "infoTypes": [
      {
       "name": "PHONE_TOKEN"
      }
     ],
     "primitiveTransformation": {
      "cryptoReplaceFfxFpeConfig": {
       "cryptoKey": {
        "unwrapped": {
         "key": "YWJjZGVmZ2hpamtsbW5vcA=="
        }
       },
       "commonAlphabet": "NUMERIC",
       "surrogateInfoType": {
        "name": "PHONE_TOKEN"
       }
      }
     }
    }
   ]
  }
 },
 "inspectConfig": {
  "customInfoTypes": [
   {
    "infoType": {
     "name": "PHONE_TOKEN"
    },
    "surrogateType": {
    }
   }
  ]
 },
 "item": {
  "value": "My phone number is PHONE_TOKEN(10):9617256398"
 }
}

Salida de JSON:

{
  "item":{
    "value":"My phone number is 4359916732"
  },
  "overview":{
    "transformedBytes":"26",
    "transformationSummaries":[
      {
        "infoType":{
          "name":"PHONE_TOKEN"
        },
        "transformation":{
          "cryptoReplaceFfxFpeConfig":{
            "cryptoKey":{
              "unwrapped":{
                "key":"YWJjZGVmZ2hpamtsbW5vcA=="
              }
            },
            "commonAlphabet":"NUMERIC",
            "surrogateInfoType":{
              "name":"PHONE_TOKEN"
            }
          }
        },
        "results":[
          {
            "count":"1",
            "code":"SUCCESS"
          }
        ],
        "transformedBytes":"26"
      }
    ]
  }
}

Cloud DLP reidentificó el número de teléfono satisfactoriamente (4359916732).

Recursos

Consulta Desidentifica datos sensibles en contenidos de texto a fin de obtener más información sobre cómo usar Cloud DLP para seudonimizar, desidentificar y reidentificar datos sensibles.