使用 R 的关系 table 中的数据屏蔽

Data masking in relational table using R

我正在尝试以不损害参照完整性的方式屏蔽数据。

我的 table 客户有此数据:

客户table

Customer_ID | Customer_Name | Address                                     | Phone        | Product_ID
143         |  Mandy Rutter | 2465 Crim Lane. Shawneetown , New York      | 718-530-0536 | 995
142         | Rich Raymond  | 2150 Linda Street ,Eagleville ,Pennsylvania | 267-902-9185 | 876

产品Table

Product_Seq | Product_Name
995         | T-Shirt
876         | Blazer

现在我想屏蔽客户 table 中的 Product_ID(比方说)。当我屏蔽它时,转换是 995 => xyz876 => pqr

现在应该对产品 table 应用相同的掩码,否则我将不知道特定 customer_id 的 product_Name。

我尝试使用 digest 基于库的解决方案。如果我屏蔽字母数字,它会起作用,但是对于整数,它不适用。

对于masking/anonymizing,它使用以下代码:

anonymize <- function(x, algo="crc32"){
  unq_hashes <- vapply(unique(x), function(object) digest(object, algo=algo), FUN.VALUE="", USE.NAMES=TRUE)
  unname(unq_hashes[x])
}

你能告诉我这是为什么吗?是否有任何最新的屏蔽包可以在这样做时保持参照完整性?

我想到的另一个软件包是 anonymizer,但它看起来只将少数几列视为敏感列,并在屏蔽时将数字转换为字母数字。

我正在尝试从一个 DBMS 系统(一些相关的 tables)复制数据,在保持关系的同时将某些列上的数据匿名化并放入其他 DBMS 系统。

有两件事对您来说很重要

  1. 匿名
  2. 参照完整性

对于您的两个要求,您链接的博客文章中的解决方案是一个糟糕的选择。

匿名

只是散列不提供匿名性。文章还提到(但它不在代码中)你可能至少要加盐。

举个例子:

211 这样的数字将 af9fad5f 作为 CRC32 散列。如果与您共享数据的人看到这个 8char(32 位)字母数字字符串,它可能会认为这可能是 CRC32 散列。散列的好处是你不能轻易地从 af9fad5f 开始计算到 211。糟糕的是,大多数短词/哈希已经预先计算好,并且很容易在所谓的彩虹 table(例如 https://md5hashing.net/hash/crc32/af9fad5f)中查找。

这基本上意味着每个人都可以查找 crc32 哈希值背后的“明文”。 (所有其他哈希值相同)。添加盐可以防止这种情况。 (这个盐当然要保密!)

参照完整性 参照完整性得以保留。 211 将始终是 af9fad5f 作为 CRC32 哈希 - 这是静态的,没有随机影响。所以 Product_ID 将对所有 table 保持不变。这就是你需要的。

但为了确保我会使用 SHA256 而不是 CRC32。在 CRC32 中,所有内容都将映射到 8 个字符的字母数字(32 位)。如果您有大量数据 - 可能会发生散列冲突。这意味着同一个 table 中的两个 numbers/ids 实际上具有相同的哈希值。使用 SHA256 这几乎是不可能的。

总的来说,我认为使用匿名程序包似乎没问题。 (它没有得到积极维护 - 但功能似乎没问题)

install.packages("devtools")
devtools::install_github("paulhendricks/anonymizer")
# Some test data
testdata <- data.frame(t1 = c(211,11,9), t2 = c(2,3,9))
anonymizer::anonymize(testdata$t1, .algo = "sha256", .seed = 1)
anonymizer::anonymize(testdata$t2, .algo = "sha256", .seed = 1)

t1

[1] "9ebb37da5a7e1db2a0ff7d0e9aa6df5b6d27a5928ce0454a9e71655cf5a16e46"
[2] "ec3e0f47c01a40969f933b9179edee184bc2d57a77e1941fc1fe773c8ac429b6"
[3] "14439a3c932d0f133ac5f5f9b147be16b4ffd854664b58fcae922084da984e2e"

t2

[1] "03a5ed142ba102af5c8e4328f54c8785310b7a8f1881b3bb9d1803261b64e91a"
[2] "0b65dd05edbd9154c3668ce294ca875e1d079967051c06238516d1a0bb233b7c"
[3] "14439a3c932d0f133ac5f5f9b147be16b4ffd854664b58fcae922084da984e2e"

和你一样,testdata$t1testdata$t2 的最后一个散列是相同的,因为它们都是 9.

The other package I thought off was anonymizer however it looks like it treats only a few columns as sensitive and it converts numbers to alphanumeric while masking.

这是什么意思?你想让你的价值观被数值掩盖吗? (为此,您可以在 R 中将字符串转换为数值)。但至少对于产品 ID,我并没有真正看到好处。

评论补充:

@Steffen , can we somehow replace numeric values with numbers only. For example SSN is 9 digits and I want to replace it another number of 9 digits only.

是的,但是对于上面概述的基于散列的解决方案来说不是很好。可能需要您编写更多代码。这需要非常小心地完成,因为在确保 参照完整性 避免串通 预防的同时很容易遗漏一些东西re-identification)。我真的会尝试使用现有的解决方案。

您还可以查看 R 中的 sdcMicro 包。我认为它们没有关于引用完整性的内容。但是您可以通过加入 table 然后使用匿名函数(这样 product_id 只会在一列中)然后再次拆分为两个数据集来规避此问题。

我认为使用其他工具进行匿名化可能也是个好主意 - 看看这个开源工具 ARX – Data Anonymization Tool

像这样的外部 GUI 工具的缺点是,如果您计划不止一次创建匿名数据集,这可能不是一个好主意。由于您没有程序,您可以 运行.