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"