【问题标题】:Data masking in relational table using R使用 R 的关系表中的数据屏蔽
【发布时间】:2020-12-16 13:44:56
【问题描述】:

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

我的表客户有这个数据:

客户表

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

产品表

Product_Seq | Product_Name
995         | T-Shirt
876         | Blazer

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

现在应该对 Product 表应用相同的屏蔽,否则我不会知道特定 customer_id 的 product_Name。

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

对于屏蔽/匿名,它使用以下代码:

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 系统(一些相关的表)复制数据,将某些列上的数据匿名化,同时保持关系并放入其他 DBMS 系统。

【问题讨论】:

  • 在我的系统上,anonymize(1L) --> "c0fd381e"anonymize(1)(数字) --> "39b528ae""for integers it NA" 是什么意思?

标签: r data-masking anonymize


【解决方案1】:

有两件事对你来说似乎很重要

  1. 匿名
  2. 参照完整性

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

匿名

仅散列不提供匿名性。文章还提到(但不在代码中)您可能至少要添加盐。

只是一个例子:

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

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

参照完整性 保持参照完整性。 211 将始终是 af9fad5f 作为 CRC32 哈希 - 这是静态的,没有随机效应。因此,所有表的 Product_ID 都将保持不变。这是你需要的。

但只是为了确保我会使用 SHA256 而不是 CRC32。在 CRC32 中,所有内容都将映射到 8chars 字母数字(32 位)。如果你有很多数据 - 有一些哈希冲突的可能性。这意味着同一个表中的两个数字/ID 实际上具有相同的哈希值。使用 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 的倍数。

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

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

来自 cmets 的添加:

@Steffen ,我们能否以某种方式仅用数字替换数值。例如 SSN 是 9 位数字,我只想将其替换为另一个 9 位数字。

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

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

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

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

【讨论】:

  • 感谢@Steffen,我们能否以某种方式仅用数字替换数值。例如 SSN 是 9 位数字,我只想将其替换为另一个 9 位数字。
  • 当然是可能的——甚至可以带来比散列方法更好的解决方案。唯一的问题是 - 没有开箱即用的 R 包。需要一些代码以保存方式来执行此操作(意味着保持参照完整性,避免冲突并防止重新识别)。
  • 嘿,我在答案中添加了一些其他信息-也许这会有所帮助:)
  • 非常感谢您的帮助。我确实检查了 sdcmicro,但认为这对于手头的问题来说有点过头了。我能够使用您之前的建议找到解决方案。我也在检查看起来很有希望的 ARX。
猜你喜欢
  • 1970-01-01
  • 2011-09-15
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-11-16
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多