<?xml version="1.0" encoding="UTF-8"?>
<rss xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns:taxo="http://purl.org/rss/1.0/modules/taxonomy/" version="2.0">
  <channel>
    <title>topic Re: Mask Data in SAS Programming</title>
    <link>https://communities.sas.com/t5/SAS-Programming/Mask-Data/m-p/884989#M349664</link>
    <description>&lt;P&gt;I see that&amp;nbsp;&lt;SPAN&gt;SHA256 and MD5 are for&amp;nbsp;&amp;nbsp;&lt;U&gt;&lt;STRONG&gt;encryption&lt;/STRONG&gt;&lt;/U&gt; without&amp;nbsp;&lt;/SPAN&gt;&lt;U&gt;&lt;STRONG&gt;decryption&lt;/STRONG&gt;&lt;/U&gt;&lt;SPAN&gt;.&lt;/SPAN&gt;&lt;/P&gt;
&lt;P&gt;&lt;SPAN&gt;I am looking for function that can do botyh&amp;nbsp;&lt;U&gt;&lt;STRONG&gt;encryption and&amp;nbsp;decryption&amp;nbsp;&lt;/STRONG&gt;&lt;/U&gt; (So when I reciever the data set back I will be able to add the original customer ID)&lt;/SPAN&gt;&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;</description>
    <pubDate>Mon, 17 Jul 2023 05:08:10 GMT</pubDate>
    <dc:creator>Ronein</dc:creator>
    <dc:date>2023-07-17T05:08:10Z</dc:date>
    <item>
      <title>Mask Data</title>
      <link>https://communities.sas.com/t5/SAS-Programming/Mask-Data/m-p/884931#M349625</link>
      <description>Hello&lt;BR /&gt;I have a dataset which contains a field for identifying a customer ( cust_id).&lt;BR /&gt;I need to mask the cust_id (before I send it to other company).&lt;BR /&gt;Then the Other company will send me back the data set (With extra columns) and I need to create a new column with the original customer ID.&lt;BR /&gt;May anyone show code how to mask the ID column and then how to find the original customer ID value?&lt;BR /&gt;Some notes-&lt;BR /&gt;1- customer id is unique number for each row that cannot repeat.&lt;BR /&gt;2- The new masked customer id should also be unique value for each row&lt;BR /&gt;3- The target is to create a new column called masked_cust_id and then have the ability to calculate original cust_id from masked_cust_id&lt;BR /&gt;&lt;BR /&gt;Data have;&lt;BR /&gt;input cust_ID;&lt;BR /&gt;cards;&lt;BR /&gt;33948398&lt;BR /&gt;54897733&lt;BR /&gt;98376333&lt;BR /&gt;;&lt;BR /&gt;run;</description>
      <pubDate>Sun, 16 Jul 2023 13:12:59 GMT</pubDate>
      <guid>https://communities.sas.com/t5/SAS-Programming/Mask-Data/m-p/884931#M349625</guid>
      <dc:creator>Ronein</dc:creator>
      <dc:date>2023-07-16T13:12:59Z</dc:date>
    </item>
    <item>
      <title>Re: Mask Data</title>
      <link>https://communities.sas.com/t5/SAS-Programming/Mask-Data/m-p/884933#M349627</link>
      <description>&lt;P&gt;Just make a new dataset that has the two id's.&amp;nbsp;&lt;/P&gt;
&lt;P&gt;The masked id can probably just be generated sequentially.&lt;/P&gt;
&lt;PRE&gt;&lt;CODE class=" language-sas"&gt;data masked_cust_id ;
  set have;
  by cust_id;
  if first.cust_id;
  masked_cust_id + 1 ;
  keep cust_id masked_cust_id;
run;&lt;/CODE&gt;&lt;/PRE&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;Then when you want to send out the actual data merge the two and drop the real id.&amp;nbsp;&lt;/P&gt;
&lt;PRE&gt;&lt;CODE class=" language-sas"&gt;data for_export ;
  merge masked_cust_id real_data(in=in2);
  by cust_id;
  if in2;
  drop cust_id;
run;&lt;/CODE&gt;&lt;/PRE&gt;
&lt;P&gt;&lt;SPAN&gt;And when you get back data merge again and add back the real id.&lt;/SPAN&gt;&lt;/P&gt;
&lt;PRE&gt;&lt;CODE class=" language-sas"&gt;data want ;
  merge masked_cust_id for_import(in=in2);
  by masked_cust_id;
  if in2;
run;&lt;/CODE&gt;&lt;/PRE&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;</description>
      <pubDate>Sun, 16 Jul 2023 15:17:57 GMT</pubDate>
      <guid>https://communities.sas.com/t5/SAS-Programming/Mask-Data/m-p/884933#M349627</guid>
      <dc:creator>Tom</dc:creator>
      <dc:date>2023-07-16T15:17:57Z</dc:date>
    </item>
    <item>
      <title>Re: Mask Data</title>
      <link>https://communities.sas.com/t5/SAS-Programming/Mask-Data/m-p/884938#M349632</link>
      <description>Thank you for the reply. However I forgot to mention that let's assume that it is forbidden by the rules to create such backup data set that convert fake customer  id to real customer id. I would like to find other solution that convert real customer  id to fake customer  id and then can convert it back from fake customer id to real  customer  id,thanks</description>
      <pubDate>Sun, 16 Jul 2023 18:16:29 GMT</pubDate>
      <guid>https://communities.sas.com/t5/SAS-Programming/Mask-Data/m-p/884938#M349632</guid>
      <dc:creator>Ronein</dc:creator>
      <dc:date>2023-07-16T18:16:29Z</dc:date>
    </item>
    <item>
      <title>Re: Mask Data</title>
      <link>https://communities.sas.com/t5/SAS-Programming/Mask-Data/m-p/884943#M349633</link>
      <description>&lt;BLOCKQUOTE&gt;&lt;HR /&gt;&lt;a href="https://communities.sas.com/t5/user/viewprofilepage/user-id/159549"&gt;@Ronein&lt;/a&gt;&amp;nbsp;wrote:&lt;BR /&gt;Thank you for the reply. However I forgot to mention that let's assume that it is forbidden by the rules to create such backup data set that convert fake customer id to real customer id. I would like to find other solution that convert real customer id to fake customer id and then can convert it back from fake customer id to real customer id,thanks&lt;HR /&gt;&lt;/BLOCKQUOTE&gt;
&lt;P&gt;Then you are probably out of luck.&amp;nbsp; You would need to create some type of algorithm for encrypting the values that you need to be able to reverse.&amp;nbsp; That means someone could break it and convert the values back to the original ids.&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;It is probably safer to store the mapping in a secure location than to use a breakable algorithm.&lt;/P&gt;</description>
      <pubDate>Sun, 16 Jul 2023 18:57:35 GMT</pubDate>
      <guid>https://communities.sas.com/t5/SAS-Programming/Mask-Data/m-p/884943#M349633</guid>
      <dc:creator>Tom</dc:creator>
      <dc:date>2023-07-16T18:57:35Z</dc:date>
    </item>
    <item>
      <title>Re: Mask Data</title>
      <link>https://communities.sas.com/t5/SAS-Programming/Mask-Data/m-p/884961#M349647</link>
      <description>May you show an example for such alogirthm  in sas code?</description>
      <pubDate>Sun, 16 Jul 2023 20:33:29 GMT</pubDate>
      <guid>https://communities.sas.com/t5/SAS-Programming/Mask-Data/m-p/884961#M349647</guid>
      <dc:creator>Ronein</dc:creator>
      <dc:date>2023-07-16T20:33:29Z</dc:date>
    </item>
    <item>
      <title>Re: Mask Data</title>
      <link>https://communities.sas.com/t5/SAS-Programming/Mask-Data/m-p/884972#M349653</link>
      <description>&lt;P&gt;Here is how we do it using the SAS MD5 function. This produces a unique and reproducable key that can't be (easily) unencrypted so you need to keep a table of the original and encrypted keys to match back to.&lt;/P&gt;
&lt;PRE&gt;&lt;CODE class=" language-sas"&gt;data want;
  Cust_ID = '12345678';
  Cust_ID_Encrypted = put(md5(Cust_ID),$hex16.);
  put _all_;
run;&lt;/CODE&gt;&lt;/PRE&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;</description>
      <pubDate>Sun, 16 Jul 2023 21:42:38 GMT</pubDate>
      <guid>https://communities.sas.com/t5/SAS-Programming/Mask-Data/m-p/884972#M349653</guid>
      <dc:creator>SASKiwi</dc:creator>
      <dc:date>2023-07-16T21:42:38Z</dc:date>
    </item>
    <item>
      <title>Re: Mask Data</title>
      <link>https://communities.sas.com/t5/SAS-Programming/Mask-Data/m-p/884973#M349654</link>
      <description>&lt;P&gt;You either need to keep&lt;/P&gt;
&lt;P&gt;- a translation dataset&lt;/P&gt;
&lt;P&gt;or&lt;/P&gt;
&lt;P&gt;- the encryption/decryption code and the key&lt;/P&gt;
&lt;P&gt;in a safe location. Both methods therefore provide the same level of security. Since a randomly created key mapping kept in a dataset is much easier to implement, use this method.&lt;/P&gt;</description>
      <pubDate>Sun, 16 Jul 2023 21:53:45 GMT</pubDate>
      <guid>https://communities.sas.com/t5/SAS-Programming/Mask-Data/m-p/884973#M349654</guid>
      <dc:creator>Kurt_Bremser</dc:creator>
      <dc:date>2023-07-16T21:53:45Z</dc:date>
    </item>
    <item>
      <title>Re: Mask Data</title>
      <link>https://communities.sas.com/t5/SAS-Programming/Mask-Data/m-p/884986#M349662</link>
      <description>&lt;P&gt;Sorry, you didnt create data sets-Real_Data&amp;nbsp; &amp;nbsp;and&amp;nbsp; For_Import&lt;/P&gt;</description>
      <pubDate>Mon, 17 Jul 2023 04:52:29 GMT</pubDate>
      <guid>https://communities.sas.com/t5/SAS-Programming/Mask-Data/m-p/884986#M349662</guid>
      <dc:creator>Ronein</dc:creator>
      <dc:date>2023-07-17T04:52:29Z</dc:date>
    </item>
    <item>
      <title>Re: Mask Data</title>
      <link>https://communities.sas.com/t5/SAS-Programming/Mask-Data/m-p/884987#M349663</link>
      <description>&lt;P&gt;Okay , however when I get back the data set then I want to have the ability to add back the real cust_ID.&lt;/P&gt;
&lt;P&gt;How can I do it?&lt;/P&gt;
&lt;P&gt;You didn't add this step here and it is critical step&lt;/P&gt;
&lt;PRE&gt;&lt;CODE class=" language-sas"&gt;Data tbl_have;
input cust_ID X Y Z;
cards;
33948398 10 20 30
54897733 11 12 13
98376333 40 60 80
;
run;

data want;
set tbl_have;
Cust_ID_Encrypted = put(md5(Cust_ID),$hex16.);
run;
&lt;/CODE&gt;&lt;/PRE&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;</description>
      <pubDate>Mon, 17 Jul 2023 04:56:37 GMT</pubDate>
      <guid>https://communities.sas.com/t5/SAS-Programming/Mask-Data/m-p/884987#M349663</guid>
      <dc:creator>Ronein</dc:creator>
      <dc:date>2023-07-17T04:56:37Z</dc:date>
    </item>
    <item>
      <title>Re: Mask Data</title>
      <link>https://communities.sas.com/t5/SAS-Programming/Mask-Data/m-p/884989#M349664</link>
      <description>&lt;P&gt;I see that&amp;nbsp;&lt;SPAN&gt;SHA256 and MD5 are for&amp;nbsp;&amp;nbsp;&lt;U&gt;&lt;STRONG&gt;encryption&lt;/STRONG&gt;&lt;/U&gt; without&amp;nbsp;&lt;/SPAN&gt;&lt;U&gt;&lt;STRONG&gt;decryption&lt;/STRONG&gt;&lt;/U&gt;&lt;SPAN&gt;.&lt;/SPAN&gt;&lt;/P&gt;
&lt;P&gt;&lt;SPAN&gt;I am looking for function that can do botyh&amp;nbsp;&lt;U&gt;&lt;STRONG&gt;encryption and&amp;nbsp;decryption&amp;nbsp;&lt;/STRONG&gt;&lt;/U&gt; (So when I reciever the data set back I will be able to add the original customer ID)&lt;/SPAN&gt;&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;</description>
      <pubDate>Mon, 17 Jul 2023 05:08:10 GMT</pubDate>
      <guid>https://communities.sas.com/t5/SAS-Programming/Mask-Data/m-p/884989#M349664</guid>
      <dc:creator>Ronein</dc:creator>
      <dc:date>2023-07-17T05:08:10Z</dc:date>
    </item>
    <item>
      <title>Re: Mask Data</title>
      <link>https://communities.sas.com/t5/SAS-Programming/Mask-Data/m-p/884990#M349665</link>
      <description>&lt;P&gt;&lt;a href="https://communities.sas.com/t5/user/viewprofilepage/user-id/159549"&gt;@Ronein&lt;/a&gt;&amp;nbsp; - When they send back their data with Cust_ID_Encrypted, just match it back to the Want dataset which has both the encrypted and unencrypted customer IDs.&amp;nbsp;&amp;nbsp;&lt;/P&gt;</description>
      <pubDate>Mon, 17 Jul 2023 05:42:35 GMT</pubDate>
      <guid>https://communities.sas.com/t5/SAS-Programming/Mask-Data/m-p/884990#M349665</guid>
      <dc:creator>SASKiwi</dc:creator>
      <dc:date>2023-07-17T05:42:35Z</dc:date>
    </item>
    <item>
      <title>Re: Mask Data</title>
      <link>https://communities.sas.com/t5/SAS-Programming/Mask-Data/m-p/884998#M349670</link>
      <description>&lt;P&gt;SAS does not provide a two-way encryption/decryption function like AES, so you would have to roll your own for an implementation of one such (reasonably secure) algorithm.&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;Using the RAND function and keeping a mapping dataset in a safe place (read: the location of the original data) works, is easy to implement, and does not violate data security/protection.&lt;/P&gt;</description>
      <pubDate>Mon, 17 Jul 2023 07:23:05 GMT</pubDate>
      <guid>https://communities.sas.com/t5/SAS-Programming/Mask-Data/m-p/884998#M349670</guid>
      <dc:creator>Kurt_Bremser</dc:creator>
      <dc:date>2023-07-17T07:23:05Z</dc:date>
    </item>
    <item>
      <title>Re: Mask Data</title>
      <link>https://communities.sas.com/t5/SAS-Programming/Mask-Data/m-p/885003#M349672</link>
      <description>&lt;P&gt;Thanks,&lt;/P&gt;
&lt;P&gt;1- I suspect that using RAND function to generate fake customer ID&amp;nbsp; can lead to duplicate problem.&lt;/P&gt;
&lt;P&gt;Please remember that Customer ID should be unique value for each customer .&lt;/P&gt;
&lt;P&gt;Then, using sequence number as fake customer number can be better.&lt;/P&gt;
&lt;P&gt;What do you think?&lt;/P&gt;
&lt;P&gt;2-I understand that in SAS there is no built in function that&amp;nbsp;provide a two-way encryption/decryption.&lt;/P&gt;
&lt;P&gt;My question is maybe anyone created such algorithm via SAS code ?&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;</description>
      <pubDate>Mon, 17 Jul 2023 08:19:56 GMT</pubDate>
      <guid>https://communities.sas.com/t5/SAS-Programming/Mask-Data/m-p/885003#M349672</guid>
      <dc:creator>Ronein</dc:creator>
      <dc:date>2023-07-17T08:19:56Z</dc:date>
    </item>
    <item>
      <title>Re: Mask Data</title>
      <link>https://communities.sas.com/t5/SAS-Programming/Mask-Data/m-p/885008#M349674</link>
      <description>&lt;P&gt;Using a sequence weakens your encryption, as the original order becomes part of the encryption algorithm.&lt;/P&gt;
&lt;P&gt;It also forces you to keep a mapping dataset, as the order may (will) change when new keys are inserted in your source data.&lt;/P&gt;
&lt;P&gt;To prevent duplicates, you use the following method:&lt;/P&gt;
&lt;UL&gt;
&lt;LI&gt;create the empty mapping dataset with two variables (original key, new key)&lt;/LI&gt;
&lt;LI&gt;in the DATA step, read this dataset into two hash objects; one uses the original key as key, and the new key as data, the other uses the new key as key&lt;/LI&gt;
&lt;LI&gt;for every observation, check if a new key is already defined in hash #1&lt;/LI&gt;
&lt;LI&gt;if not found, create a new key with RAND in a DO UNTIL no match is found in hash #2; use the ADD method for both hashes&lt;/LI&gt;
&lt;LI&gt;write to the output, omitting the original key&lt;/LI&gt;
&lt;LI&gt;at the end of the step, save the contents of hash #1 back to the mapping dataset&lt;/LI&gt;
&lt;/UL&gt;
&lt;P&gt;When you receive data back, use the mapping dataset in a hash with new key as key and original key as data.&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;To your question #2: I seriously doubt anyone has gone to the length of creating a reliable two-way encryption method, and if, they'll want money for their work.&lt;/P&gt;</description>
      <pubDate>Mon, 17 Jul 2023 08:51:16 GMT</pubDate>
      <guid>https://communities.sas.com/t5/SAS-Programming/Mask-Data/m-p/885008#M349674</guid>
      <dc:creator>Kurt_Bremser</dc:creator>
      <dc:date>2023-07-17T08:51:16Z</dc:date>
    </item>
    <item>
      <title>Re: Mask Data</title>
      <link>https://communities.sas.com/t5/SAS-Programming/Mask-Data/m-p/885019#M349677</link>
      <description>&lt;PRE&gt;&lt;CODE class=" language-sas"&gt;Data have;
input cust_ID $;

length encode decode $ 200;
encode=put(cust_ID,$hex64.);
decode=input(encode,$hex64.);

cards;
33948398
54897733
98376333
;
run;
proc print;run;&lt;/CODE&gt;&lt;/PRE&gt;
&lt;P&gt;&lt;span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="Ksharp_0-1689594299570.png" style="width: 400px;"&gt;&lt;img src="https://communities.sas.com/t5/image/serverpage/image-id/85813i8BBF10F02D49CE9D/image-size/medium?v=v2&amp;amp;px=400" role="button" title="Ksharp_0-1689594299570.png" alt="Ksharp_0-1689594299570.png" /&gt;&lt;/span&gt;&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;</description>
      <pubDate>Mon, 17 Jul 2023 11:44:45 GMT</pubDate>
      <guid>https://communities.sas.com/t5/SAS-Programming/Mask-Data/m-p/885019#M349677</guid>
      <dc:creator>Ksharp</dc:creator>
      <dc:date>2023-07-17T11:44:45Z</dc:date>
    </item>
    <item>
      <title>Re: Mask Data</title>
      <link>https://communities.sas.com/t5/SAS-Programming/Mask-Data/m-p/885031#M349683</link>
      <description>&lt;P&gt;I've developed some time ago a masking framework for masking PII columns in one environment and then transfer the masked tables to another environment (from PROD to DEV).&amp;nbsp;&lt;/P&gt;
&lt;P&gt;Important in this scenario was that all columns in the masked tables still had the same attributes (like data type and length). For this reason any approach using MD5, SHA etc. was not suitable.&amp;nbsp;&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;In my case just using a sequence number for the masked data was no issue. And it's much easier to manage than using a random number because the moment you're generating the number randomly you need to also build a check that you haven't generated the same number already for another cleartext value. ...and because of the birthday paradigm the probability to do so is higher than one would intuitively assume.&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;If just using a sequence number the only thing you need to pay some attention to is to not use the algorithm on data that's sorted by the cleartext variable you want to mask (like a customer number that's often also "sequential").&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;To implement something fully dynamically that's also works for character variables with short length and alphanumerical strings takes a bit more but for your use case things can be kept rather simple.&amp;nbsp;&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;It was for my use case important that the same cleartext value always resulted in the same masked values even when running&amp;nbsp;the masking algorithm for multiple tables and tables from multiple months and at different times.&amp;nbsp;&lt;/P&gt;
&lt;P&gt;The only way this can work is to store and maintain a permanent masking lookup table with key-value pairs of cleartext and masked values.&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;Here what could work for you and meets all the above formulated requirements.&lt;/P&gt;
&lt;PRE&gt;&lt;CODE class=" language-sas"&gt;libname perm "%sysfunc(pathname(work))";

/* sample data */
data work.have;
  do cust_id=4,1,99999,10,1,5,4;
    obs_num+1;
    output;
  end;
run;

/* create permanent masking lookup table if not exists */
/* - key-value pairs of cleartext-masked values        */
%if %sysfunc(exist(perm.cust_mask)) ne 1 %then
  %do;
    data perm.cust_masklookup(index=;
      stop;
      set work.have(keep=cust_id);
      cust_id_masked=cust_id;
    run;
  %end;

/* create table with masked data */
data work.masked;
  if _n_=1 then 
    do;
      if 0 then set perm.cust_masklookup(rename=(cust_id_masked=__cust_id_masked));
      /* permanent masking lookup table with data masked in previous runs */
      dcl hash __h1(dataset:'perm.cust_masklookup(rename=(cust_id_masked=__cust_id_masked))');
      __h1.defineKey('cust_id');
      __h1.defineData('__cust_id_masked');
      __h1.defineDone();
      /* mask lookup table to collect with masked values created in this run */
      dcl hash __h1_new(dataset:'perm.cust_masklookup(obs=0 rename=(cust_id_masked=__cust_id_masked))');
      __h1_new.defineKey('cust_id');
      __h1_new.defineData('cust_id','__cust_id_masked');
      __h1_new.defineDone();

    end;
  call missing(of _all_);

  set work.have end=last;

  if __h1.find() ne 0 and __h1_new.find() ne 0 then
    do;
      __cust_id_masked=sum(__h1.num_items,__h1_new.num_items,76589);
      __rc=__h1_new.add(key:cust_id, data:cust_id, data:__cust_id_masked);
    end;
  cust_id=__cust_id_masked;

  /* write newly created key-value pairs of cleartext/masked values to work table */
  if last then __h1_new.output(dataset:'work.cust_masklookup_new(rename=(__cust_id_masked=cust_id_masked))');

  drop __:;

run;

/* append newly created masked values to permanent lookup table */
proc append base=perm.cust_masklookup data=work.cust_masklookup_new;
run;quit;

/* unmask values */
data work.un_masked;
  if _n_=1 then
    do;
      if 0 then set perm.cust_masklookup(rename=(cust_id_masked=__cust_id_masked));
      dcl hash h1(dataset:'perm.cust_masklookup(rename=(cust_id_masked=__cust_id_masked))');
      h1.defineKey('__cust_id_masked');
      h1.defineData('cust_id');
      h1.defineDone();
    end;
  call missing(of _all_);
  set work.masked;
  if h1.find(key:cust_id) ne 0 then 
    do;
      put 'Clear text key not found in masking lookup table';
      put cust_id=;
      abort;
    end;
  drop __:;
run;

/* print the various tables */
title 'PERM: cust_masklookup';
proc print data=perm.cust_masklookup_new;
run;
title 'have';
proc print data=work.have;
run;
title 'masked';
proc print data=work.masked;
run;
title 'un_masked';
proc print data=work.un_masked;
run;
title;
&lt;/CODE&gt;&lt;/PRE&gt;
&lt;P&gt;Please spend some time to understand above code before you start to ask questions about it.&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;</description>
      <pubDate>Mon, 17 Jul 2023 12:12:01 GMT</pubDate>
      <guid>https://communities.sas.com/t5/SAS-Programming/Mask-Data/m-p/885031#M349683</guid>
      <dc:creator>Patrick</dc:creator>
      <dc:date>2023-07-17T12:12:01Z</dc:date>
    </item>
    <item>
      <title>Re: Mask Data</title>
      <link>https://communities.sas.com/t5/SAS-Programming/Mask-Data/m-p/885085#M349704</link>
      <description>&lt;P&gt;Hi&amp;nbsp;&lt;a href="https://communities.sas.com/t5/user/viewprofilepage/user-id/159549"&gt;@Ronein&lt;/a&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;The SAS encryption algoritms&amp;nbsp; will always generate the SAME KEY for a given value. This can be used in the following way:&lt;/P&gt;
&lt;P&gt;1. Generate data to the external part with an encrypted key only.&lt;/P&gt;
&lt;P&gt;2. Join your original and the returned data on the encrypted key, which you generate once more from the original ID in the join condition.&lt;/P&gt;
&lt;P&gt;This way, you don't have and don't need a data set with both the original key and the encrypted key. I think that should satisfy all requirements.&lt;/P&gt;
&lt;PRE&gt;&lt;CODE class=" language-sas"&gt;* What you have;
data have;
  ID = 123456;
  Name = 'Ronein';
run;

* You make encrypted data to external part;
data xport; set have;
  drop ID;
  ID_encrypt = put(md5(cats(put(ID,12.))),$hex32.);
run;

* External part returns data with added information;
data return;
  set xport;
  Occupation = 'SAS Programmer';
run;

* You merge added infornmation onto orig data;
proc sql;
  create table want as
    select
      a.ID,
      a.Name,
      b.Occupation
    from have as a full outer join return as b
    on put(md5(cats(put(a.ID,12.))),$hex32.) = b.ID_encrypt;
quit;
&lt;/CODE&gt;&lt;/PRE&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;</description>
      <pubDate>Mon, 17 Jul 2023 14:50:01 GMT</pubDate>
      <guid>https://communities.sas.com/t5/SAS-Programming/Mask-Data/m-p/885085#M349704</guid>
      <dc:creator>ErikLund_Jensen</dc:creator>
      <dc:date>2023-07-17T14:50:01Z</dc:date>
    </item>
    <item>
      <title>Re: Mask Data</title>
      <link>https://communities.sas.com/t5/SAS-Programming/Mask-Data/m-p/885242#M349786</link>
      <description>&lt;P&gt;&lt;a href="https://communities.sas.com/t5/user/viewprofilepage/user-id/159549"&gt;@Ronein&lt;/a&gt;&amp;nbsp;Just encoding via $hex64 doesn't cut it. Anyone who knows how you encoded the values can easily decode them.&amp;nbsp;&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;But reading your original requirements again: So if "the other company" adds data (columns) to your table then they also need to know the customer. How else would they be capable to add the data to the right customer. If this is true then it's likely more about secure transmission of data and not about masking PII columns. Is that correct?&lt;/P&gt;</description>
      <pubDate>Tue, 18 Jul 2023 11:31:48 GMT</pubDate>
      <guid>https://communities.sas.com/t5/SAS-Programming/Mask-Data/m-p/885242#M349786</guid>
      <dc:creator>Patrick</dc:creator>
      <dc:date>2023-07-18T11:31:48Z</dc:date>
    </item>
    <item>
      <title>Re: Mask Data</title>
      <link>https://communities.sas.com/t5/SAS-Programming/Mask-Data/m-p/885257#M349790</link>
      <description>The real story is that by law it is forbidden for me to keep real customer id so i need to keep other fake value and my target is to be able to come back to real customer id ( from fake customer  id)</description>
      <pubDate>Tue, 18 Jul 2023 12:28:57 GMT</pubDate>
      <guid>https://communities.sas.com/t5/SAS-Programming/Mask-Data/m-p/885257#M349790</guid>
      <dc:creator>Ronein</dc:creator>
      <dc:date>2023-07-18T12:28:57Z</dc:date>
    </item>
    <item>
      <title>Re: Mask Data</title>
      <link>https://communities.sas.com/t5/SAS-Programming/Mask-Data/m-p/885263#M349796</link>
      <description>&lt;P&gt;[EDIT:] (after sending this I saw that&amp;nbsp;&lt;a href="https://communities.sas.com/t5/user/viewprofilepage/user-id/159"&gt;@Tom&lt;/a&gt;&amp;nbsp;already wrote that "no encrypting" answer)&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;The question was already answered but the following also satisfies your 1,2, and 3 requirements:&lt;/P&gt;
&lt;PRE&gt;&lt;CODE class=" language-sas"&gt;Data have;
input cust_ID someValue $;
cards;
33948398 A
54897733 B
98376333 C
54897733 D
;
run;

proc sort data=have(keep=cust_ID) out=lookup nodupkey;
  by cust_ID;
run;

data lookup;
  set lookup;
  masked_cust_ID + 1;
run;

proc print data=lookup;
run;&lt;/CODE&gt;&lt;/PRE&gt;
&lt;P&gt;Since it is you who provides input data you have full control on the "masking" and no encryption function is needed.&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;All the best&lt;/P&gt;
&lt;P&gt;Bart&lt;/P&gt;</description>
      <pubDate>Tue, 18 Jul 2023 13:08:11 GMT</pubDate>
      <guid>https://communities.sas.com/t5/SAS-Programming/Mask-Data/m-p/885263#M349796</guid>
      <dc:creator>yabwon</dc:creator>
      <dc:date>2023-07-18T13:08:11Z</dc:date>
    </item>
  </channel>
</rss>

