2

I’m making a webapp which encrypts each user’s data, using AES-256, with a unique key for each account. I’m thinking about adding external signon via the “Sign in with Google” scheme. However, I’ve done some digging, and I’m not sure if it’s possible in my situation.

Right now, I store the user’s password hash using 10 iterations of the Argon2 Hash, and process logins using the Argon2 built-in hash compare. As I understand it, the Google OAuth2 would replace this part just fine. However, it’s the next part that I’m concerned about.

For each user, I generate a unique, random string 50 characters long using the Apache Commons RandomStringUtils.random(...); function (incorporating both letters & numbers). I use this string as the master encryption key for the account. All the user’s content is encrypted using this key. The actual encryption is done using the Spring AES Password-Based Cipher, where this master key string is passed in as the encryption password.

But here’s the problem: I then generate a random BCrypt Salt (configured to 12 iterations) unique for each user, and store this salt raw in the user’s account record in the DB. When the user creates their account, I take their raw text password, and hash it with BCrypt, using their account unique BCrypt salt. This BCrypt hash of their raw text password is the Meta-Key I use to encrypt their master key. I then store their encrypted master key in their Account DB record. Then, when the user logs in, I take their raw text password, generate the hash again using the salt stored in the DB, and use it as the Meta-Key to decrypt their master key from the DB. I then re-encrypt their master key using the server’s global private key (the same for all users), and then embed the Server-Encrypted master key into a JWT token and send it to the client to act as their stateless Token. When they make a request, they pass the token back, the webserver extracts the master key from the token, decrypts it with the server’s global private key, and then uses it to decrypt the user’s data.

Unless you see something majorly wrong with my design, my questions is: if I switch to OAuth, the user will no longer be providing me with a password, I will only be getting a token from the OAuth provider (Google in this case). But that token will be different each time they log in. I need something that is unique to each user, that is also static and will be exactly the same every time they log in. But it also needs to be private & non-reproducible, so I can’t use something like their Google Account GUID (assuming they even give you access to something like that), because that would be accessible to other apps/users.

Does OAuth provide any mechanism for a some kind of token/ID which is both Private & Unique to the User/App pair, and also Static across separate logins? At this point, I’m coming to the conclusion that OAuth is impossible in my situation, but I thought I’d see if anyone had any ideas. I’m open to redesigning my security process, but it must maintain a unique encryption key for each user.

Thank you for your time.

-Yurelle

  • can't you just generate a key and tie it to the account in your DB? that aside, it sounds overly-complicated with the diversity of hashes and software packages in-use. – dandavis Jun 20 '17 at 18:52
  • But then the key would be raw in the DB. I'm trying to make it secure enough that even if an attacker got access to the DB, they still couldn't get any of the content. What part is too much? I used 2 different hashing algorithms to generate different hashes. I suppose I could have just used a different salt, but I wanted to make it obvious in the code which one went where, so there was little risk of an accidental overlap that could result in a catastrophic security failure. – Yurelle Jun 20 '17 at 19:43
  • Also, I generally thought it best practice to use industry-standard libraries whenever possible rather than rolling your own, especially with anything security related. I even read a few threads a while back where people were fairly strongly encouraging people to not use the bare-metal Java Encryption, but to use any well established, high-level abstracted library to ensure you don't do it wrong. But I could be wrong. – Yurelle Jun 20 '17 at 19:48
  • sounds to me like you should collect the password from the user, otherwise how would you store it without storing it? oauth is for authentication, not privacy, and you apparently don't have enough low-level pieces as-is (within your self-imposed restrictions). re: too much: that's my take-away trying to understand your explanation of the setup; it could be fine, but with much diversity comes much base knowledge and maintenance. if it fit on a t-shirt, everyone can tell it's safe at a glance... – dandavis Jun 20 '17 at 19:50
  • Your T-shirt analogy makes sense. I'll kick around the design and see if I can make it simpler, but right now, aside from the separate hash algorithms, I don't see how it could get much simpler while maintaining the same level of security. Although, perhaps that's just because I already understand how it works, so I don't see it for the spaghetti that it is. – Yurelle Jun 20 '17 at 19:58

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Browse other questions tagged or ask your own question.