Home > Software design >  R: Encrypt string via cyphr, sending to JSON and then converting from JS back to string causes issue
R: Encrypt string via cyphr, sending to JSON and then converting from JS back to string causes issue

Time:12-18

I want to encrypt a string, and then format it to JSON, so I can send it to a database/the frontend safely. However, when retrieving encrypted data from the database, I need to go from JSON back to an R-string, which is an issue:

key <- cyphr::key_sodium(sha256(charToRaw("password123")))
encrypted <- cyphr::encrypt_string("my secret string", key)
encrypted_raw <- rawToChar(encrypted)
json_encrypted <- jsonlite::toJSON(encrypted_raw)
json_encrypted #This variable is then send to the database and retrieved again
json_decrypted <- jsonlite::fromJSON(json_encrypted)
decrypted_raw <- charToRaw(json_decrypted)
cyphr::decrypt_string(decrypted_raw, key)
#Expected output: "my secret string"
#Received output: "Error in decrypt(unpack(msg), key()) : Failed to decrypt"

It seems like it is a problem with the jsonlite package: If I remove this step, it works:

key <- cyphr::key_sodium(sha256(charToRaw("password123")))
encrypted <- cyphr::encrypt_string("my secret string", key)
encrypted_raw <- rawToChar(encrypted)
decrypted_raw <- charToRaw(encrypted_raw)
cyphr::decrypt_string(decrypted_raw, key)
#Expected output: "my secret string"
#Received output: "my secret string"

How can I encrypt a string, pass it to JSON, and then retrieve it from JSON and decrypt it afterwards? Thanks

CodePudding user response:

jsonlite::toJSON() does accept raw input. By default it is encoded as base64. Thus, when reimporting it, you need to convert the base64 string to raw with base64enc::base64decode(). After that you should have no problem decoding your secret.

library(jsonlite)
library(sodium)
library(cyphr)
library(base64enc)

key <- "password123" |> 
  charToRaw() |> 
  sha256() |> 
  key_sodium()

sec <- "my secret string" |> 
  encrypt_string(key) 

sec |> 
  toJSON() |> 
  fromJSON() |> 
  base64decode() |> 
  decrypt_string(key)
#> [1] "my secret string"
  • Related