Re-identify free text with FPE using a surrogate

Uses the Cloud Data Loss Prevention API to re-identify sensitive data in a string that was encrypted by format-preserving encryption (FPE) with a surrogate type. The encryption is performed with an unwrapped key.

Explore further

For detailed documentation that includes this code sample, see the following:

Code sample

C#

To learn how to install and use the client library for Sensitive Data Protection, see Sensitive Data Protection client libraries.

To authenticate to Sensitive Data Protection, set up Application Default Credentials. For more information, see Set up authentication for a local development environment.


using System;
using Google.Api.Gax.ResourceNames;
using Google.Cloud.Dlp.V2;
using Google.Protobuf;
using static Google.Cloud.Dlp.V2.CryptoReplaceFfxFpeConfig.Types;

public class ReidentifyFreeTextWithFpeUsingSurrogate
{
    public static ReidentifyContentResponse ReidentifyFreeText(
        string projectId,
        string text,
        string unwrappedKey,
        FfxCommonNativeAlphabet alphabet = FfxCommonNativeAlphabet.Numeric,
        InfoType surrogateType = null)
    {
        // Instantiate dlp client.
        var dlp = DlpServiceClient.Create();

        // Construct the infoType which will be used as surrogate type and infoType both.
        var infoType = surrogateType ?? new InfoType { Name = "PHONE_TOKEN" };

        // Construct crypto replace config using crypto key name and wrapped key.
        var cryptoReplaceFfxFpeConfig = new CryptoReplaceFfxFpeConfig
        {
            CryptoKey = new CryptoKey
            {
                Unwrapped = new UnwrappedCryptoKey
                {
                    Key = ByteString.FromBase64(unwrappedKey)
                }
            },
            CommonAlphabet = alphabet,
            SurrogateInfoType = infoType
        };

        // Construct the re-identify config using crypto replace config.
        var reidentifyConfig = new DeidentifyConfig
        {
            InfoTypeTransformations = new InfoTypeTransformations
            {
                Transformations =
                {
                    new InfoTypeTransformations.Types.InfoTypeTransformation
                    {
                        PrimitiveTransformation = new PrimitiveTransformation
                        {
                            CryptoReplaceFfxFpeConfig = cryptoReplaceFfxFpeConfig
                        }
                    }
                }
            }
        };

        // Construct the inspect config with the help of custom info type.
        var inspectConfig = new InspectConfig
        {
            CustomInfoTypes =
            {
                new CustomInfoType
                {
                    InfoType = infoType,
                    SurrogateType = new CustomInfoType.Types.SurrogateType()
                }
            }
        };

        // Construct the request.
        var request = new ReidentifyContentRequest
        {
            ParentAsLocationName = new LocationName(projectId, "global"),
            ReidentifyConfig = reidentifyConfig,
            InspectConfig = inspectConfig,
            Item = new ContentItem { Value = text }
        };

        // Call the API.
        ReidentifyContentResponse response = dlp.ReidentifyContent(request);

        // Inspect the response.
        Console.WriteLine($"Re-identified content: {response.Item.Value}");
        return response;
    }
}

Go

To learn how to install and use the client library for Sensitive Data Protection, see Sensitive Data Protection client libraries.

To authenticate to Sensitive Data Protection, set up Application Default Credentials. For more information, see Set up authentication for a local development environment.

import (
	"context"
	"encoding/base64"
	"fmt"
	"io"

	dlp "cloud.google.com/go/dlp/apiv2"
	"cloud.google.com/go/dlp/apiv2/dlppb"
)

// reidentifyFreeTextWithFPEUsingSurrogate re-identifies free text with FPE using surrogate
func reidentifyFreeTextWithFPEUsingSurrogate(w io.Writer, projectID, inputStr, surrogateType, unWrappedKey string) error {
	// projectId := "your-project-id"
	// inputStr := "My phone number is PHONE_TOKEN(10):4068372189"
	// surrogateType := "PHONE_TOKEN"
	// unWrappedKey := "hXribiHR6kvVKmj5ptTZLRTj8+u0eBQzwcrEPwyGhe8="

	ctx := context.Background()

	// Initialize a client once and reuse it to send multiple requests. Clients
	// are safe to use across goroutines. When the client is no longer needed,
	// call the Close method to cleanup its resources.
	client, err := dlp.NewClient(ctx)
	if err != nil {
		return err
	}

	// Closing the client safely cleans up background resources.
	defer client.Close()

	// The wrapped key is base64-encoded, but the library expects a binary
	// string, so decode it here.
	keyBytes, err := base64.StdEncoding.DecodeString(unWrappedKey)
	if err != nil {
		return err
	}

	// using the unwrapped key and surrogate info type construct cryptoReplaceConfig
	cryptoReplaceConfig := &dlppb.CryptoReplaceFfxFpeConfig{
		CryptoKey: &dlppb.CryptoKey{
			Source: &dlppb.CryptoKey_Unwrapped{
				Unwrapped: &dlppb.UnwrappedCryptoKey{
					Key: keyBytes,
				},
			},
		},
		Alphabet: &dlppb.CryptoReplaceFfxFpeConfig_CommonAlphabet{
			CommonAlphabet: dlppb.CryptoReplaceFfxFpeConfig_NUMERIC,
		},
		SurrogateInfoType: &dlppb.InfoType{
			Name: surrogateType,
		},
	}

	// construct infoType transformations
	infoTypeTransformations := &dlppb.InfoTypeTransformations{
		Transformations: []*dlppb.InfoTypeTransformations_InfoTypeTransformation{
			{
				PrimitiveTransformation: &dlppb.PrimitiveTransformation{
					Transformation: &dlppb.PrimitiveTransformation_CryptoReplaceFfxFpeConfig{
						CryptoReplaceFfxFpeConfig: cryptoReplaceConfig,
					},
				},
			},
		},
	}

	// construct re-identify config
	reIdentifyConfig := &dlppb.DeidentifyConfig{
		Transformation: &dlppb.DeidentifyConfig_InfoTypeTransformations{
			InfoTypeTransformations: infoTypeTransformations,
		},
	}

	// construct inspect config to pass in req
	inspectConfig := &dlppb.InspectConfig{
		CustomInfoTypes: []*dlppb.CustomInfoType{
			{
				InfoType: &dlppb.InfoType{
					Name: surrogateType,
				},
				Type: &dlppb.CustomInfoType_SurrogateType_{
					SurrogateType: &dlppb.CustomInfoType_SurrogateType{},
				},
			},
		},
	}

	// Construct the de-identification request to be sent by the client.
	req := &dlppb.ReidentifyContentRequest{
		Parent:           fmt.Sprintf("projects/%s/locations/global", projectID),
		ReidentifyConfig: reIdentifyConfig,
		InspectConfig:    inspectConfig,
		Item: &dlppb.ContentItem{
			DataItem: &dlppb.ContentItem_Value{
				Value: inputStr,
			},
		},
	}

	// Send the request.
	r, err := client.ReidentifyContent(ctx, req)
	if err != nil {
		return err
	}

	// Print the result.
	fmt.Fprintf(w, "output: %v", r.GetItem().GetValue())
	return nil
}

Java

To learn how to install and use the client library for Sensitive Data Protection, see Sensitive Data Protection client libraries.

To authenticate to Sensitive Data Protection, set up Application Default Credentials. For more information, see Set up authentication for a local development environment.


import com.google.cloud.dlp.v2.DlpServiceClient;
import com.google.common.io.BaseEncoding;
import com.google.privacy.dlp.v2.ContentItem;
import com.google.privacy.dlp.v2.CryptoKey;
import com.google.privacy.dlp.v2.CryptoReplaceFfxFpeConfig;
import com.google.privacy.dlp.v2.CustomInfoType;
import com.google.privacy.dlp.v2.DeidentifyConfig;
import com.google.privacy.dlp.v2.InfoType;
import com.google.privacy.dlp.v2.InfoTypeTransformations;
import com.google.privacy.dlp.v2.InspectConfig;
import com.google.privacy.dlp.v2.LocationName;
import com.google.privacy.dlp.v2.PrimitiveTransformation;
import com.google.privacy.dlp.v2.ReidentifyContentRequest;
import com.google.privacy.dlp.v2.ReidentifyContentResponse;
import com.google.privacy.dlp.v2.UnwrappedCryptoKey;
import com.google.protobuf.ByteString;
import java.io.IOException;
import java.util.Base64;
import javax.crypto.KeyGenerator;
import javax.crypto.SecretKey;

public class ReidentifyFreeTextWithFpeUsingSurrogate {
  public static void main(String[] args) throws Exception {
    // TODO(developer): Replace these variables before running the sample.

    // The Google Cloud project id to use as a parent resource.
    String projectId = "your-project-id";
    // The string to de-identify.
    String textToDeIdentify = "My phone number is 4359916731";
    // The base64-encoded AES-256 key to use.
    String base64EncodedKey = "your-base64-encoded-key";

    // Obtain the de-identified text.
    String textToReIdentify =
        DeidentifyFreeTextWithFpeUsingSurrogate.deIdentifyWithFpeSurrogate(
            projectId, textToDeIdentify, base64EncodedKey);

    reIdentifyWithFpeSurrogate(projectId, textToReIdentify, base64EncodedKey);
  }

  // Re-identifies sensitive data in a string that was encrypted by Format Preserving Encryption
  // (FPE) with surrogate type.
  public static void reIdentifyWithFpeSurrogate(
      String projectId, String textToReIdentify, String unwrappedKey) throws IOException {
    // Initialize client that will be used to send requests. This client only needs to be created
    // once, and can be reused for multiple requests. After completing all of your requests, call
    // the "close" method on the client to safely clean up any remaining background resources.
    try (DlpServiceClient dlp = DlpServiceClient.create()) {
      // Specify what content you want the service to re-identify.
      ContentItem contentItem = ContentItem.newBuilder().setValue(textToReIdentify).build();
      CustomInfoType.SurrogateType surrogateType =
          CustomInfoType.SurrogateType.newBuilder().build();

      // Specify the surrogate type used at time of de-identification.
      InfoType surrogateInfoType = InfoType.newBuilder().setName("PHONE_TOKEN").build();

      CustomInfoType customInfoType =
          CustomInfoType.newBuilder()
              .setInfoType(surrogateInfoType)
              .setSurrogateType(surrogateType)
              .build();
      InspectConfig inspectConfig =
          InspectConfig.newBuilder().addCustomInfoTypes(customInfoType).build();

      // Specify an unwrapped crypto key.
      UnwrappedCryptoKey unwrappedCryptoKey =
          UnwrappedCryptoKey.newBuilder()
              .setKey(ByteString.copyFrom(BaseEncoding.base64().decode(unwrappedKey)))
              .build();
      CryptoKey cryptoKey = CryptoKey.newBuilder().setUnwrapped(unwrappedCryptoKey).build();

      // Specify how to decrypt the previously de-identified information.
      CryptoReplaceFfxFpeConfig cryptoReplaceFfxFpeConfig =
          CryptoReplaceFfxFpeConfig.newBuilder()
              .setCryptoKey(cryptoKey)
              // Set of characters in the input text. For more info, see
              // https://cloud.google.com/dlp/docs/reference/rest/v2/organizations.deidentifyTemplates#DeidentifyTemplate.FfxCommonNativeAlphabet
              .setCommonAlphabet(CryptoReplaceFfxFpeConfig.FfxCommonNativeAlphabet.NUMERIC)
              .setSurrogateInfoType(surrogateInfoType)
              .build();

      PrimitiveTransformation primitiveTransformation =
          PrimitiveTransformation.newBuilder()
              .setCryptoReplaceFfxFpeConfig(cryptoReplaceFfxFpeConfig)
              .build();

      InfoTypeTransformations.InfoTypeTransformation infoTypeTransformation =
          InfoTypeTransformations.InfoTypeTransformation.newBuilder()
              .setPrimitiveTransformation(primitiveTransformation)
              .build();

      InfoTypeTransformations transformations =
          InfoTypeTransformations.newBuilder().addTransformations(infoTypeTransformation).build();

      DeidentifyConfig reidentifyConfig =
          DeidentifyConfig.newBuilder().setInfoTypeTransformations(transformations).build();

      // Combine configurations into a request for the service.
      ReidentifyContentRequest request =
          ReidentifyContentRequest.newBuilder()
              .setParent(LocationName.of(projectId, "global").toString())
              .setItem(contentItem)
              .setInspectConfig(inspectConfig)
              .setReidentifyConfig(reidentifyConfig)
              .build();
      // Send the request and receive response from the service.
      ReidentifyContentResponse response = dlp.reidentifyContent(request);

      // Print the results.
      System.out.println("Text after re-identification: " + response.getItem().getValue());
    }
  }
}

Node.js

To learn how to install and use the client library for Sensitive Data Protection, see Sensitive Data Protection client libraries.

To authenticate to Sensitive Data Protection, set up Application Default Credentials. For more information, see Set up authentication for a local development environment.

// Imports the Google Cloud Data Loss Prevention library
const DLP = require('@google-cloud/dlp');

// Instantiates a client
const dlp = new DLP.DlpServiceClient();

// The project ID to run the API call under
// const projectId = 'my-project';

// The string to Re-identify
// const string = 'PHONE_TOKEN(10):########';

// The set of characters to replace sensitive ones with
// For more information, see https://cloud.google.com/dlp/docs/reference/rest/v2/organizations.deidentifyTemplates#ffxcommonnativealphabet
// const alphabet = 'NUMERIC';

// InfoTypes
// const infoTypes = [{name: 'PHONE_NUMBER'}];

// Surrogate Type
// const surrogateType = 'PHONE_TOKEN';

// The base64-encoded AES-256 key to use
// const unwrappedKey = 'YWJjZGVmZ2hpamtsbW5vcA==';

async function reidentifyWithFpeSurrogate() {
  // Specify an unwrapped crypto key.
  unwrappedKey = Buffer.from(unwrappedKey, 'base64');

  // Specify how the info from the inspection should be encrypted.
  const cryptoReplaceFfxFpeConfig = {
    cryptoKey: {
      unwrapped: {
        key: unwrappedKey,
      },
    },
    commonAlphabet: alphabet,
    surrogateInfoType: {name: surrogateType},
  };

  // Construct the inspect configuration.
  const inspectConfig = {
    customInfoTypes: [
      {
        infoType: {
          name: surrogateType,
        },
        surrogateType: {},
      },
    ],
  };

  // Set the text to be re-identified.
  const item = {value: string};

  // Combine configurations into a request for the service.
  const request = {
    parent: `projects/${projectId}/locations/global`,
    reidentifyConfig: {
      infoTypeTransformations: {
        transformations: [
          {
            primitiveTransformation: {
              cryptoReplaceFfxFpeConfig: cryptoReplaceFfxFpeConfig,
            },
          },
        ],
      },
    },
    item: item,
    inspectConfig: inspectConfig,
  };
  // Run re-identification request
  const [response] = await dlp.reidentifyContent(request);
  const reidentifiedItem = response.item;
  // Print results
  console.log(reidentifiedItem.value);
}
reidentifyWithFpeSurrogate();

PHP

To learn how to install and use the client library for Sensitive Data Protection, see Sensitive Data Protection client libraries.

To authenticate to Sensitive Data Protection, set up Application Default Credentials. For more information, see Set up authentication for a local development environment.


/**
 * Re-identify free text with FPE using a surrogate.
 * Uses the Cloud Data Loss Prevention API to re-identify sensitive data in a string that was
 * encrypted by format-preserving encryption (FPE) with a surrogate type. The encryption is
 * performed with an unwrapped key.
 *
 * @param string $callingProjectId  The GCP Project ID to run the API call under.
 * @param string $string            The string to reidentify.
 * @param string $unwrappedKey      The base64-encoded AES-256 key to use.
 * @param string $surrogateTypeName The name of the surrogate custom info type to used during
 * the encryption process.
 */
function reidentify_free_text_with_fpe_using_surrogate(
    // TODO(developer): Replace sample parameters before running the code.
    string $callingProjectId,
    string $string,
    string $unwrappedKey = 'YWJjZGVmZ2hpamtsbW5vcA==',
    string $surrogateTypeName = 'PHONE_TOKEN'
): void {
    // Instantiate a client.
    $dlp = new DlpServiceClient();

    $parent = "projects/$callingProjectId/locations/global";

    // Specify an unwrapped crypto key.
    $unwrapped = (new UnwrappedCryptoKey())
        ->setKey(base64_decode($unwrappedKey));

    $cryptoKey = (new CryptoKey())
        ->setUnwrapped($unwrapped);

    // Specify the surrogate type used at time of de-identification.
    $surrogateType = (new InfoType())
        ->setName($surrogateTypeName);

    // The set of characters to replace sensitive ones with.
    // For more information, see https://cloud.google.com/dlp/docs/reference/rest/V2/organizations.deidentifyTemplates#ffxcommonnativealphabet
    $commonAlphabet = FfxCommonNativeAlphabet::NUMERIC;

    // Specify how to decrypt the previously de-identified information.
    $cryptoReplaceFfxFpeConfig = (new CryptoReplaceFfxFpeConfig())
        ->setCryptoKey($cryptoKey)
        ->setCommonAlphabet($commonAlphabet)
        ->setSurrogateInfoType($surrogateType);

    // Create the information transform configuration objects.
    $primitiveTransformation = (new PrimitiveTransformation())
        ->setCryptoReplaceFfxFpeConfig($cryptoReplaceFfxFpeConfig);

    $infoTypeTransformation = (new InfoTypeTransformation())
        ->setPrimitiveTransformation($primitiveTransformation);

    $infoTypeTransformations = (new InfoTypeTransformations())
        ->setTransformations([$infoTypeTransformation]);

    // Create the reidentification configuration object.
    $reidentifyConfig = (new DeidentifyConfig())
        ->setInfoTypeTransformations($infoTypeTransformations);

    // Create the inspect configuration object.
    // Specify the type of info the inspection will look for.
    $infotype = (new InfoType())
        ->setName($surrogateTypeName);

    $customInfoType = (new CustomInfoType())
        ->setInfoType($infotype)
        ->setSurrogateType((new SurrogateType()));

    $inspectConfig = (new InspectConfig())
        ->setCustomInfoTypes([$customInfoType]);

    // Specify the content to be re-identify.
    $content = (new ContentItem())
        ->setValue($string);

    // Run request.
    $reidentifyContentRequest = (new ReidentifyContentRequest())
        ->setParent($parent)
        ->setReidentifyConfig($reidentifyConfig)
        ->setInspectConfig($inspectConfig)
        ->setItem($content);
    $response = $dlp->reidentifyContent($reidentifyContentRequest);

    // Print the results.
    printf($response->getItem()->getValue());
}

Python

To learn how to install and use the client library for Sensitive Data Protection, see Sensitive Data Protection client libraries.

To authenticate to Sensitive Data Protection, set up Application Default Credentials. For more information, see Set up authentication for a local development environment.

import base64

import google.cloud.dlp


def reidentify_free_text_with_fpe_using_surrogate(
    project: str,
    input_str: str,
    alphabet: str = "NUMERIC",
    surrogate_type: str = "PHONE_TOKEN",
    unwrapped_key: str = "YWJjZGVmZ2hpamtsbW5vcA==",
) -> None:
    """Uses the Data Loss Prevention API to reidentify sensitive data in a
    string that was encrypted by Format Preserving Encryption (FPE) with
    surrogate type. The encryption is performed with an unwrapped key.
    Args:
        project: The Google Cloud project id to use as a parent resource.
        input_str: The string to deidentify (will be treated as text).
        alphabet: The set of characters to replace sensitive ones with. For
            more information, see https://cloud.google.com/dlp/docs/reference/
            rest/v2beta2/organizations.deidentifyTemplates#ffxcommonnativealphabet
        surrogate_type: The name of the surrogate custom info type to used
            during the encryption process.
        unwrapped_key: The base64-encoded AES-256 key to use.
    Returns:
        None; the response from the API is printed to the terminal.
    """

    # Instantiate a client
    dlp = google.cloud.dlp_v2.DlpServiceClient()

    # Convert the project id into a full resource id.
    parent = f"projects/{project}/locations/global"

    # The wrapped key is base64-encoded, but the library expects a binary
    # string, so decode it here.
    unwrapped_key = base64.b64decode(unwrapped_key)

    # Construct Deidentify Config
    transformation = {
        "primitive_transformation": {
            "crypto_replace_ffx_fpe_config": {
                "crypto_key": {"unwrapped": {"key": unwrapped_key}},
                "common_alphabet": alphabet,
                "surrogate_info_type": {"name": surrogate_type},
            }
        }
    }

    reidentify_config = {
        "info_type_transformations": {"transformations": [transformation]}
    }

    inspect_config = {
        "custom_info_types": [
            {"info_type": {"name": surrogate_type}, "surrogate_type": {}}
        ]
    }

    # Convert string to item
    item = {"value": input_str}

    # Call the API
    response = dlp.reidentify_content(
        request={
            "parent": parent,
            "reidentify_config": reidentify_config,
            "inspect_config": inspect_config,
            "item": item,
        }
    )

    # Print results
    print(response.item.value)

What's next

To search and filter code samples for other Google Cloud products, see the Google Cloud sample browser.