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.aesencryption将导致“\”,并且前面的字符被误解。 为了避免这种情况,将密钥转换为raw并将原始字节保存为单个string。 使用paste0collapse来粘贴代表每个字节的字符( 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版本(漂亮的字母数字)原始字节来避免将反斜杠误解为转义字符的整个问题。