R将包含反斜杠的string从文件传递给charToRaw,而不会转义
我试图从一个密码保护的文件读入一个数据库到R的密钥,并将其转换为raw,如下所示:
假设我的密钥是\xb@\xErd\xD5b\x1bs
。 我的目标是获得相同的原始密钥,当将密钥作为string直接传递给charToRaw
函数时:
rawkey1 <- charToRaw("\xb@\xErd\xD5b\x1bs") > rawkey1 [1] 0b 40 0e 72 64 d5 62 1b 73
我可以将其保存在.csv文件中,并将其读回到R:
savemykey <- data.table(keyinbytes = "\xb@\xErd\xD5b\x1bs") write.csv(savemykey, file = "My_key.csv") mykey <- read.csv("My_key.csv", header = TRUE, stringsAsFactors = FALSE)
然后我可以将其转换为raw,并产生所需的结果:
> rawkey2 = charToRaw(mykey$keyinbytes) > rawkey2 [1] 0b 40 0e 72 64 d5 62 1b 73
直接传递给charToRaw
函数以及读取包含密钥的csv文件的原始密钥是相同的:
> rawkey1 == rawkey2 [1] TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE
到现在为止还挺好。 唯一的问题是密钥是包含敏感信息的数据库的关键,所以我想将其存储在受密码保护的文件中。
我能想到的唯一方法就是用Microsoft Excel(用excel.link包读取并提供密码作为参数); 然而,在创build.xlsx文件时,反斜杠在读回时被解释为转义。这会导致从字符到原始的转换不正确:
library(xlsx) write.xlsx2(savemykey, file = "My_key.xlsx", append = FALSE)
然后打开Microsoft Excel文件,指定密码“mypassword”,保存并用excel.link包读回:
library(excel.link) mykey <- xl.read.file("My_key.xlsx", xl.sheet = 1, password = "mypassword") # Re-running the conversion: rawkey3 = charToRaw(mykey$keyinbytes) > rawkey3 [1] 3f 40 3f 72 64 d5 62 3f 73
如果我将这个结果与第一个键进行比较,它不匹配:
> rawkey3 == rawkey1 [1] FALSE TRUE FALSE TRUE TRUE TRUE TRUE FALSE TRUE
这是因为在Microsoft Excel文件中读取时,R已将反斜杠解释为转义符,转义后面的字符并将其replace为“?”,如下所示:
# Key as assigned object in R: > savemykey$keyinbytes [1] "\v@\016rdÕb\033s" # Key read in from Microsoft Excel file: > mykey$keyinbytes [1] "?@?rdÕb?s"
根据我迄今为止的尝试,似乎如果将密钥保存为任何可以保存为纯文本(.csv,.txt或直接在R脚本中并将其来源)的文件types,密钥是用反斜杠的正确评估读回R,并转换为正确的原始字节模式。 但是,我一直无法find任何密码保护纯文本文件/ .csv或R脚本的方法。
我想要么:
-
find一种密码保护的纯文本格式文件,当读回到R中时,保留对密钥中反斜杠的评估,并且读入方法将密码作为参数;
-
find一种方法来读取密码保护的Microsoft Excel文件中的密钥,而没有反斜杠被转义。
任何想法如何做到这一点将不胜感激。
我find了一种方法来创buildencryption的文本文件(可以是数据,或者可能是R脚本,稍作修改)。 一个脚本来创build一个encryption的文件,然后在使用摘要包读取它之后解密它已经由Stephane Doyen在这里创build: https : //github.com/sdoyen/r_password_crypt 。
这工作如下:
# Load libraries # This does the encryption and decryption require(digest) # This allows users to enter a password securely with a masked widget require(getPass) # I'll put the details I want to encrypt into a data.table require(data.table)
创build并input密码(长度必须是16个字母数字字符的倍数,例如'myfavouritepw123'):
mypw <- charToRaw(getPass("Enter the password for your login details file:"))
加载Stephane的write.aes和read.aes函数:
# To encrypt and password protect a file: write.aes <- function(df,filename, key) { require(digest) zz <- textConnection("out","w") write.csv(df,zz, row.names=F) close(zz) out <- paste(out,collapse="\n") raw <- charToRaw(out) raw <- c(raw,as.raw(rep(0,16-length(raw)%%16))) aes <- AES(key,mode="ECB") aes$encrypt(raw) writeBin(aes$encrypt(raw),filename) } # To decrypt the file with a password after reading it back in: read.aes <- function(filename,key) { require(digest) dat <- readBin(filename,"raw",n=1000) aes <- AES(key,mode="ECB") raw <- aes$decrypt(dat, raw=TRUE) txt <- rawToChar(raw[raw>0]) read.csv(text=txt, stringsAsFactors = F) }
创build您想要encryption的文件:
注意:使用write.aes
encryption将导致“\”,并且前面的字符被误解。 为了避免这种情况,将密钥转换为raw并将原始字节保存为单个string。 使用paste0
和collapse
来粘贴代表每个字节的字符( sep
将不起作用)。
mysecretlogin1 <- data.table(keyinbytes = paste0(charToRaw("\xb@\xErd\xD5b\x1bs"), collapse = " "))
使用前面创build的密码作为密钥,将data.table写入带有write.aes的encryption文件:
write.aes(df = mysecretlogin1, filename = "mysecretkey.txt", key = mypw)
重新读取文件并用您的密码解密:
mypw <- charToRaw(getPass("Enter the password for your login details file:")) mysecretlogin2 <- data.table(read.aes(filename = "mysecretkey.txt", key = mypw))
检查导出和导入的文件是否相同:
> mysecretlogin1 == mysecretlogin2 keyinbytes [1,] TRUE
要以原始forms使用密钥,可以使用此函数将string转换回原始字节(在每个字节之前添加“0x”,使其可以作为原始向量传递到不带引号的列表):
makeraw <- function(characterstring) { mystring <- strsplit(characterstring, " ") mystring <- lapply(mystring, function(x) paste0("0x", x)) mystring <- as.raw(unlist(mystring)) mystring }
应用function:
myrawkey <- makeraw(mysecretlogin2$keyinbytes)
检查它已经工作:
> myrawkey [1] 0b 40 0e 72 64 d5 62 1b 73 > str(myrawkey) raw [1:9] 0b 40 0e 72 ... > is.raw(myrawkey) [1] TRUE
这个解决scheme中的'key'(没有双关语意思!)是通过将键字存储为string版本(漂亮的字母数字)原始字节来避免将反斜杠误解为转义字符的整个问题。