【问题标题】:Data Masking in SAS: Scrambling Sensitive observations at character levelSAS 中的数据屏蔽:字符级别的加扰敏感观察
【发布时间】:2013-05-11 01:20:55
【问题描述】:

我正在处理 SAS 中包含敏感客户识别信息的客户数据。挑战在于以保持数字/字母/字母数字的方式屏蔽该字段。我找到了一种在 SAS(BXOR、BOR、BAND)中使用按位函数的方法,但输出中充满了 SAS 无法处理/排序/合并等的特殊字符。

我也想过根据一个键对字段本身进行加扰,但无法看穿它。以下是挑战:

1) 它必须是基于密钥的 2) 必须是可逆的。 3) 屏蔽/加扰字段必须是数字/字母/字母数字,才能在 SAS 中使用。 4)要屏蔽的字段既有字母又有数字,但长度不同,有数百万个观察值。

任何关于如何实现这种掩蔽/加扰的提示将不胜感激:(

【问题讨论】:

  • 使用查找表或格式怎么样?
  • “仅数字/字母/字母数字”是什么意思?还能是什么??或者你是说它必须保持相同的类型[所以数字变量必须保持数字,而字符变量必须保持字符]?
  • 另外,我们需要什么样的安全性? “阻止某人阅读屏幕上的数据”是否安全,或者“有人可能试图破解的银行记录”是否安全?
  • Rob - 客户拒绝了一次查找,称如果有人愿意,很容易破解该密码。我终于开发了一个使用多个查找的代码,希望就足够了。 Joe - 输出不应包含任何特殊字符。我尝试将输入转换为 ASCII,然后转换为二进制,对它们执行操作,然后将它们转换回来,但输出是乱码,供 SAS 读取。该变量是客户的唯一标识符,因此客户希望隐藏该值。

标签: encryption sas masking scramble data-masking


【解决方案1】:

这是一个简单的基于密钥的解决方案。我在这里介绍数据步骤解决方案,然后将介绍一个 FCMP 版本。我将所有内容保持在 48 到 127 的范围内(数字、字母和常见字符,例如 @ >

data construct_key;
length keystr $1500;
do _t = 1 to 1500;
  _rannum = ceil(ranuni(7)*80);
  *if _rannum=12 then _rannum=-15;
  substr(keystr,_t,1)=byte(47+_rannum);

end;
call symput('keystr',keystr);
run;
%put %bquote(&keystr);



data encrypted;
set sashelp.class;
retain key "&keystr";
length name_encrypt $30;
do _t = 1 to length(name);
  substr(name_encrypt,_t,1) = byte(mod(rank(substr(name,_t,1)) + rank(substr(key,1,1))-94,80)+47);
  key = substr(key,2);
end;
keep name:;
run;

data unencrypted;
set encrypted;
retain key "&keystr";
length name_unenc $30;
do _t = 1 to length(name_encrypt);
  substr(name_unenc,_t,1) = byte(
      mod(80+rank(substr(name_encrypt,_t,1)) - rank(substr(key,1,1)),80)
+47);
  key = substr(key,2);
end;
run;

在此解决方案中,有中等级别的加密 - 具有 80 个可能值的密钥不足以阻止真正老练的黑客,但对于大多数用途来说足够强大。您需要将密钥本身或种子传递给密钥算法才能解密;如果您多次使用它,请确保每次都选择一个新种子(而不是与数据相关的东西)。如果您使用零(或非正整数)作为种子,您将有效地保证每次都有一个新密钥,但您必须传递密钥本身而不是种子,这可能会带来一些数据安全问题(显然,密钥本身可以是由恶意用户获取,并且必须存储在与数据不同的位置)。通过种子传递密钥可能更好,因为您可以通过电话或通过某种预先安排的种子列表口头传递。

我不确定我是否普遍推荐这种方法;一种更好的方法很可能是使用高级加密方法(例如 PGP)简单地加密整个 SAS 数据集。您的确切解决方案可能会有所不同,但如果您有一些客户信息对于您的流程的大多数步骤实际上并不是必需的,那么您最好将该信息与其余(非敏感)数据分开并仅合并在需要的时候。

例如,我有一个流程,我为客户提取样本以进行医疗保健调查。我从除了数字唯一标识符之外没有客户信息的数据集中选择有效记录;一旦我将样本范围缩小到有效记录,然后我从单独的数据集中附加客户信息并创建邮件文件(存储在加密目录中)。这样可以尽可能长时间地保持数据不敏感。这并不完美 - 唯一的数字标识符仍然意味着有联系,即使它与项目之外的任何人都不知道 - 但它尽可能长时间地保证我们的安全。

这是 FCMP 版本:

%let keylength=5;
%let seed=15;

proc fcmp outlib=work.funcs.test;
subroutine encrypt(value $,key $);
  length key $&keylength.;
  outargs value,key;
  do _t = 1 to lengthc(value);
    substr(value,_t,1) = byte(mod(rank(substr(value,_t,1)) + rank(substr(key,1,1))-62,96)+31);
    key = substr(key,2)||substr(key,1,1);
  end;
endsub;

subroutine unencrypt(value $,key $);
  length key $&keylength.;
  outargs value,key;
  do _t = 1 to lengthc(value);
    substr(value,_t,1) = byte(mod(96+rank(substr(value,_t,1)) - rank(substr(key,1,1)),96)+31);
    key = substr(key,2)||substr(key,1,1);
  end;
endsub;

subroutine gen_key(seed,keystr $);
  outargs keystr;
  length keystr $&keylength.;
  do _t = 1 to &keylength.;
    _rannum = ceil(ranuni(seed)*80);    
    substr(keystr,_t,1)=byte(47+_rannum);
  end;
endsub;
quit;

options cmplib=work.funcs;



data encrypted;
set sashelp.class;
length key $&keylength.;
retain key ' '; *the missing is to avoid the uninitialized variable warning;
if _n_ = 1 then call gen_key(&seed,key);
call encrypt(name,key);
drop key;
run;

data unencrypted;
set encrypted;
length key $&keylength.;
retain key ' ';
if _n_ = 1 then call gen_key(&seed,key);
call unencrypt(name,key);
run;

这更健壮一些;它允许 32 到 127 个字符而不是 48 个字符,这意味着它可以成功处理空格。 (Tab 仍然无法正确解码 - 它会变成一个“k”。)您将种子传递给调用 gen_key,然后它在该过程的其余部分使用该密钥。

不言而喻,这不能保证满足您的目的和/或成为一个安全的解决方案,如果您有大量的安全需求,您应该咨询安全专家。本帖不为任何目的提供任何保证,发帖者不承担因使用该帖而产生的任何和所有责任。

【讨论】:

    【解决方案2】:

    SAS 在其网站上有一篇关于如何加密特定变量的文章。希望这会对您有所帮助。

    link

    【讨论】:

    • 这是我最后用的:)
    • 链接已失效。请尽量在答案中给出最重要的信息,以免将来的用户因为链接失效而感到沮丧。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2023-03-29
    • 1970-01-01
    • 2020-05-01
    • 2015-07-18
    • 2017-03-22
    • 2018-08-15
    • 1970-01-01
    相关资源
    最近更新 更多