Edited at

RとPythonで匿名化


はじめに

今回の勉強会のテーマは「匿名化」

経済産業省で作成されている、事業者が匿名加工情報の具体的な作成方法を検討するにあたっての参考資料を参照しながら、対象データの匿名化処理を実施しました

https://www.meti.go.jp/press/2016/08/20160808002/20160808002.html

https://www.meti.go.jp/press/2016/08/20160808002/20160808002-1.pdf

目的は、Rの講習会の内容をpythonではどうやって書くの?を復習かねて記録することです


環境

windows10 Pro 64bit

R :3.6.1

RStudio :1.2.1335

Google Colaboratoryを使用

Python :3.6.8


なにするの

①データの暗号化処理

②データの匿名化処理

今回は匿名化の必要性についての座学が多かったため処理は少なめでした


暗号化

可逆可能な方法でデータを符号化すること(かな?)

データの再利用が必要な場合に利用

共通鍵暗号方式:RC4,DES、AES 等

公開鍵暗号方式:DH,DH,RSA,ECC など


匿名化

データの特定化を避けることが目的のため、可逆性は問わない。むしろいらない。

パスワードなどは、データそのものに意味がなく匿名化されたデータ同士が同じであれば使用用途を満たせる。

ハッシュ関数などで符号化を行う。

データベースの場合は、識別子(個人を特定できるデータ)を匿名化してもその他のデータの組み合わせで特定可能な場合がある。どの程度特定化が困難か?はk-匿名化で示される。

ハッシュ化のアルゴは色々あります

['sha1', 'sha224', 'sha256', 'sha384', 'sha3_224', 'sha3_256', 'sha3_384', 'sha3_512', 'sha512', 'shake_128', 'shake_256']


Rのコード

①データの暗号化処理

Rではsaferを用いて暗号化ができます

が、、この暗号化アルゴは何なんでしょう?

ドキュメントをさっと見たんですが分かりませんでした、、

https://cran.r-project.org/web/packages/safer/safer.pdf#search='R+safer'

#packageのインストール

install.packages("digest")
install.packages("safer")
library(safer)
library(digest)

install.packages("tidyverse")
library(tidyverse)

# abcde を key を secret として暗号化
str <- "abcde"
str %>% safer::encrypt_string(key="secret") -> enc_res
#str %>% encrypt_string(key="secret") -> enc_res
enc_res

> enc_res
[1] "Np2yuAUVDyLK6WKFSHyhVqxWbHTG"

# key を間違えると複合化できません
enc_res %>% safer::decrypt_string(key="secre")

Error in safer::decrypt_string(., key = "secre") :
Unable to decrypt. Ensure that the input was generated by 'encrypt_string'.

②データの匿名化処理

Rではdigestを用いてハッシュ関数を使用できます

https://cran.r-project.org/web/packages/digest/digest.pdf#search='R+digest'

#暗号化で用いたstr 'abcde'をハッシュ化します

algo_list <- c("md5", "sha1", "crc32", "sha256", "sha512",
"xxhash32", "xxhash64", "murmur32", "spookyhash")
for(i in 1:9){
res <- str %>%
digest::digest(algo = algo_list[[i]]) %>%
print()
}

[1] "7ab53e2465ca2aebc97740ee54bdee23"
[1] "e2bec62fc7f686f4cc9f4e4a2be15d3132b79251"
[1] "1ed3d69b"
[1] "f7107ae8895bafe851d7c392138b849074fc0cd15d527dc979a712739d732c3f"
[1] "91727d0e21cd6991a13eaf8f4882ac0710b57d6221c95e767d29963b562da45757a709caf80073d9b5979b73938ca9bacf8313bc7f30b86a82e4a3aeac95ada4"
[1] "5e828f4f"
[1] "44a5ade049cd23e2"
[1] "f07b8be8"
[1] "3e4e2953dd0812f83a0eb4708ecccfe7"

digestはベクトル化されていない関数のため、dataframeなどで使用するとうまく動作しない問題があるそうです。

(Rだとしばしば問題になるようです、、pythonでは聞いたことないのですがどうなんでしょう?)

「匿名加工情報作成マニュアル」P5 にあるようなデータを想定してデータを匿名化

そのままではすべて同じ値になってしまう

# csvファイルを読み込み

customer01 <- read.csv("xxx.csv")

#hash カラムを作成し契約者IDをハッシュ化してみる
customer01 <- customer01 %>%
mutate(hash = digest(契約者ID))

customer01

#結果はすべて同じ値になってしまう
hash
1 1c6e3b479dbd166e11f85907196de69a
2 1c6e3b479dbd166e11f85907196de69a
3 1c6e3b479dbd166e11f85907196de69a
4 1c6e3b479dbd166e11f85907196de69a
5 1c6e3b479dbd166e11f85907196de69a
6 1c6e3b479dbd166e11f85907196de69a
7 1c6e3b479dbd166e11f85907196de69a
8 1c6e3b479dbd166e11f85907196de69a
9 1c6e3b479dbd166e11f85907196de69a
10 1c6e3b479dbd166e11f85907196de69a

sapply関数を使うことで、digestにベクトルデータを入力できる(でいいのかな?)

customer01$hash <- sapply(customer01$契約者ID, digest)

customer01

#hash カラムが正常にハッシュ化されている
hash
1 99730c015b03d5b64967e51a69fb2a0e
2 ac1b66f3dd4dd5471abcb6877e8f0eed
3 d7bc915ef4ce356c836b956ed69be4d1
4 eb67463847fd6f9deca7524cd38b9a15
5 350ad2498e32998191ca0a3127a2e9eb
6 0d046e6a38b56b72d1d2532a5034442b
7 dd3c3167624b05477813e0c936112897
8 1228a56be1f3ecbc99814f6fa8f0e8c7
9 99152d2c3e276f967140ea4c52ac3445
10 88706daa36af8945e125950d0d80d25f


Pythonのコード

①データの暗号化処理

ライブラリー pycrypto で、AESの暗号化を行えます

keyは、16,24,32バイト長にする必要あり

元データは、16バイトの倍数にする必要あり

#ライブラリーをインポート

pip install pycrypto

#AED をインポート
from Crypto.Cipher import AES

#keyと入力データを設定
secret_key = 'secretsecretsecd'
message = 'abcdefghijklopqr'

crypto = AES.new(secret_key)

cipher_data = crypto.encrypt(message)
cipher_data

b'\xf2Le\xeas\xfea\\\xc1\xb0Ug\x99\x04B\x94'

②データの匿名化処理

ライブラリー hashlib でハッシュ化できます

import hashlib

s ='abcde'
hs = hashlib.md5(s.encode('utf-8')).hexdigest()
print(hs)

ab56b4d92b40713acc5af89985d4b786

#hashlibで使用できる関数
print(dir(hashlib))

['__all__', '__builtin_constructor_cache', '__builtins__', '__cached__', '__doc__', '__file__', '__get_builtin_constructor', '__loader__', '__name__', '__package__', '__spec__', '_hashlib', 'algorithms_available', 'algorithms_guaranteed', 'blake2b', 'blake2s', 'md5', 'new', 'pbkdf2_hmac', 'scrypt', 'sha1', 'sha224', 'sha256', 'sha384', 'sha3_224', 'sha3_256', 'sha3_384', 'sha3_512', 'sha512', 'shake_128', 'shake_256']

dataframeに対して使用する場合は、関数化してapplyすれば可能です

import pandas as pd

#csvをdataframeとして読み込み
customer = pd.read_csv('xxx.csv',encoding='shift-jis')

#関数定義
def hash_tf(x):
return hashlib.md5(x.encode('utf-8')).hexdigest()

#dataframeに適用
customer['hash_ID'] = customer['契約者ID'].astype(str).apply(hash_tf)

customer['hash_ID']

0 62f249ecf0c6b67132facb2d09f6fc22fd5012da
1 f6b3bf35a478c62ee83e25f684099de2cc5d40d3
2 b9a2972621ddd5d155b37010c92e9b2fdebb6f79
3 7788648e3e62072021824b26c43323f7dc88b3c3
4 290f5053d8fee1cf06d00a2f3c0495393acf5639
5 df90bf5ca5ace2c2f77138fb5920cd23bef0d1f0
6 620d2b6aedec60b1c2442180d3ee34aa41a83986
7 eedc474694ba572ca312e2412b1e5a506bacc16e
8 39f7787b563b793dbd698d84dbfa5d9e462e7447
9 60aee79bd0c98a0d5408106b389ad62395e008d8
10 4ee7760595b71cdbe88af93cfe8545caf6e895a5