3

I have a password that I store in a plain text file. I want to obfuscate it somehow, in case someone is looking at my monitor.

Ideally, I would like to encrypt a password with another default string (say, "123") and get an obfuscated version of my password. Then, when I need password within a code, I want to decrypt the password with the same string "123". It would be also good that the lengths of obfuscated and normal passwords differ.

So, the logic should be:

encrypt(password, "123") -> obf_string
decrypt(obf_string, "123") -> password

How can I do this?

P.S. I know that it's not secure anyway, but this is what I want to have right now.

Sergey Ivanov
  • 3,719
  • 7
  • 34
  • 59
  • Andrie de Vries wrote a good article about this problem: https://www.r-bloggers.com/securely-storing-your-secrets-in-r-code/ – NJBurgo Aug 22 '16 at 10:39
  • Although the first article is more useful: http://blog.revolutionanalytics.com/2015/11/how-to-store-and-use-authentication-details-with-r.html – NJBurgo Aug 22 '16 at 10:40
  • 2
    If you are dealing with passwords, don't encrypt/decrypt; rather, use hashes. For instance `digest::digest(password)` returns an hash you can safely put in codes. When an user enters a password, you match the hash of it with the "correct" one, so you don't have to decrypt. See the wiki page https://en.wikipedia.org/wiki/Cryptographic_hash_function – nicola Aug 22 '16 at 10:58
  • @nicola the thing is I need to pass that password later on, so it's not me matching passwords. – Sergey Ivanov Aug 22 '16 at 11:04
  • @NJBurgo, I read this article, but didn't find solution to what I specified. – Sergey Ivanov Aug 22 '16 at 11:07
  • When the server is attacked the attacker will obtain the encrypted passwords and the encryption key. Try to find a way that does not include encryption the passwords. – zaph Aug 22 '16 at 12:03
  • Define the attacker, their capabilities and the value of the passwords. If you are passing the passwords along to 3rd party services you become the attack point, your security needs to be better that the 3rd parties you are passing the password to. You become exactly the target an attacker is looking for, the easiest way to compromise the 3rd party sites. The 3rd parties security, no matter how good is reduced to your security. Consider that it is your users who are at risk from poor password handling, they expect and deserve good security. – zaph Aug 22 '16 at 12:19

2 Answers2

1

A quick way to obfuscate is through random number generation, here my attempt:

encrypt <- function(password, string){
        set.seed(password)
        encr <- round(runif(nchar(string), 0, 9))
        y <- as.integer(substring(string, seq(nchar(string)), seq(nchar(string)))) + encr
        return(y)
}

decrypt <- function(password, string){
        set.seed(password)
        encr <- round(runif(nchar(string), 0, 9))
        y <- paste0(string - encr, collapse="")
        return(y)
}

Your string is e.g. 1984. You just have to pick a password, e.g. 2016.

> encrypt(2016, "1984")
[1]  3 10 16  5

You give them to encrypt() and the function returns a numeric vector of the same size of your string. To get back the string use decrypt() with your password and the vector:

> decrypt(2016, c(3,10,16,5))
[1] "1984"

A less naive alternative, that further allows text connections, is to encode/decode through base64, using the base64enc package:

install.packages("base64enc")
library(base64enc)
base64encode(c(2,0,0,6))
base64decode("AgAABg==")
000andy8484
  • 563
  • 3
  • 16
0

Following up on @zach comments, this procedure would not be safe in case of an attack. This is uniquely useful is you want to obfuscate a string (e.g. from someone passing by and looking at the screen), security is not implied in this question.

This version of my the functions I reported in the previous answer also accepts strings with numbers and letters:

obfuscate <- function(password, string){
        set.seed(password)
        vec <- substring(string, seq(nchar(string)), seq(nchar(string)))
        encr <- y <- vector("list",length(vec))
        letters <- rep(letters,2)   # prolongue letters sequence
        for (i in 1:length(vec)){
                ifelse(is.numeric(vec[i]),             # extracting encryption numbers 
                       encr[[i]] <- round(runif(1, 0, 9)),   # if numeric
                       encr[[i]] <- round(runif(1, 0, 26)))  # if letters

                ifelse( !is.na(as.numeric(vec[i])) ,   # encrypting
                        y[[i]] <- as.numeric(vec[i]) + encr[[i]],                    # if numeric
                        y[[i]] <- letters[which(letters==vec[i])[1] + encr[[i]]] )  # if letters
        }
        return(unlist(y))
}

reveal <- function(password, y){
        set.seed(password)
        for (i in 1:length(y)){ 
                ifelse(is.numeric(y[i]),             # extracting encryption numbers 
                       encr[[i]] <- round(runif(1, 0, 9)),   # if numeric
                       encr[[i]] <- round(runif(1, 0, 26)))  # if letters
                ifelse( !is.na(as.numeric(y[i])) ,   # encrypting
                        y[[i]] <- as.numeric(y[i]) - encr[[i]],                   # if numeric
                        y[[i]] <- letters[which(letters==y[i])[1] - encr[[i]]] )  # if letters
        }
        return(paste0(unlist(y), collapse=""))
}

Here is an example:

> obfuscate(2016,"a6b8")
[1] "f"  "10" "x"  "11"
Warning messages:
1: In ifelse(!is.na(as.numeric(vec[i])), y[[i]] <- as.numeric(vec[i]) +  :
  NAs introduced by coercion
2: In ifelse(!is.na(as.numeric(vec[i])), y[[i]] <- as.numeric(vec[i]) +  :
  NAs introduced by coercion

Note that the number of warnings is equal to the number of non-numeric characters. This could be suppressed with suppressWarnings() as explained in this SO question. My preference is for always expressing R warnings.

> reveal(2016,c("f","10","x","11"))
[1] "a6b8"
Warning messages:
1: In ifelse(!is.na(as.numeric(y[i])), y[[i]] <- as.numeric(y[i]) -  :
  NAs introduced by coercion
2: In ifelse(!is.na(as.numeric(y[i])), y[[i]] <- as.numeric(y[i]) -  :
  NAs introduced by coercion
Community
  • 1
  • 1
000andy8484
  • 563
  • 3
  • 16
  • While inventing enctyption is fun it is a bad idea to use it, again: ["Schneier's Law"](https://www.schneier.com/blog/archives/2011/04/schneiers_law.html): Anyone, from the most clueless amateur to the best cryptographer, can create an algorithm that he himself can't break. Futrther there is no assurance that `set.seed` is the same between systems or between software releases. – zaph Aug 22 '16 at 13:02
  • 2
    We got the point @zaph, but Sergey needs "to obfuscate somehow" a string not to recreate the enigma machine. Security is not involved in this specific question. – 000andy8484 Aug 22 '16 at 13:08
  • You named the functions `encrypt` and `decrypt`. Since it uses a key it does seem to qualify as encryption. Also, not knowing `r`, in generall warning message are not a good thing. – zaph Aug 22 '16 at 13:10
  • @zach I replied to your comments in the edited answer. – 000andy8484 Aug 22 '16 at 13:18
  • @Sergey I updated the function to allow character strings, could you please follow up or accept? – 000andy8484 Aug 24 '16 at 09:16
  • Your solution doesn't work, for example the following produces an error: reveal(2016,c("f","10","s","11")) – Parsa Jun 03 '18 at 13:45