Beefy Boxes and Bandwidth Generously Provided by pair Networks
Welcome to the Monastery
 
PerlMonks  

OT: Storing encryption keys securely

by Beatnik (Parson)
on Jan 23, 2017 at 14:42 UTC ( #1180158=perlquestion: print w/replies, xml ) Need Help??

Beatnik has asked for the wisdom of the Perl Monks concerning the following question:

Slightly OT but here goes.

I'm writing some glue code that will store an encrypted password in a database. I'm looking at different approaches on making all this as safe as possible. Hashing the password (for verification) is not really an option as I will need access to the clear-text (to pass it on to another class). I'll be taking some steps to avoid breaking the encrypted password easily but what about storing the key used to encrypt? In an ideal world, the key to encrypt won't be accessible by anyone but how can I make sure? In some way, the key must be stored somewhere.. Even with a keychain of some kind, I will still need to store the keychain key.

Thoughts?


Greetz
Beatnik
... I'm belgian but I don't play one on TV.

Replies are listed 'Best First'.
Re: OT: Storing encryption keys securely
by choroba (Bishop) on Jan 23, 2017 at 14:54 UTC
    Store it in a different database than the one that stores the passwords. Keep the two databases on different hosts.

    Can't you wrap the database serving the key into a service that asks for a passphrase on startup?

    ($q=q:Sq=~/;[c](.)(.)/;chr(-||-|5+lengthSq)`"S|oS2"`map{chr |+ord }map{substrSq`S_+|`|}3E|-|`7**2-3:)=~y+S|`+$1,++print+eval$q,q,a,
      Adding a second node adds complexity. You will need to store the credentials for that one too.. plus storing the key in clear text in the database is just a more complex way than storing it in a file. Asking the key on startup sounds OK but when updating the key (during password recovery), all existing passwords now become invalid as they cannot be re-encrypted. Thanks for the ideas.


      Greetz
      Beatnik
      ... I'm belgian but I don't play one on TV.
        > Adding a second node adds complexity

        Yes, and complexity means it's harder to hack you.

        > storing the key in clear text in the database

        I'd store it encrypted with the passphrase.

        > they cannot be re-encrypted

        What do you mean?

        #!/usr/bin/perl use strict; use warnings; use Data::Dumper; $Data::Dumper::Useqq = 1; # In reality, use a better algorithm, add salt, etc. sub encrypt { my ($password, $passphrase) = @_; my $long_passphrase = $passphrase; $long_passphrase .= $passphrase until length($password) < length $long_passphrase; substr $long_passphrase, -1, 1, q() until length($password) == length $long_passphrase; return $password ^ $long_passphrase } *decrypt = *encrypt{CODE}; # This comes from the users. my %real_passwords = ( john => 'pas$$w0rd', jane => 'bailey2012', ); # This comes from the admin. my $passphrase = 'Perl FTW!'; # This gets saved in the DB. my %stored_passwords = map { $_ => encrypt($real_passwords{$_}, $passphrase) } keys %real_passwords; print Dumper \%stored_passwords; # When changing the passphrase, just update the passwords: my $new_passphrase = 'Invalidate all passwords!'; $_ = encrypt(decrypt($_, $passphrase), $new_passphrase) for values %stored_passwords; print Dumper \%stored_passwords; # We can now retrieve the passwords using the new passphrase. print Dumper +{ map { $_ => decrypt($stored_passwords{$_}, $new_passphrase) } keys %stored_passwords };

        ($q=q:Sq=~/;[c](.)(.)/;chr(-||-|5+lengthSq)`"S|oS2"`map{chr |+ord }map{substrSq`S_+|`|}3E|-|`7**2-3:)=~y+S|`+$1,++print+eval$q,q,a,
Re: OT: Storing encryption keys securely
by BrowserUk (Pope) on Jan 24, 2017 at 14:26 UTC
    1. You should never store passwords themselves, even if encrypted, if the encryption method is reversible.
    2. You should only store the result of combining the password with a per user (derived) salt and passing it through a slow, one-way encoding algorithm.
    3. To authenticate, you obtain the password combine with the derived salt and encode again. If the result matches the stored value, you authorise.
    4. To handle the forgotten password scenario, you generate a random password, encode and replace the encoded token in your database.

      Get the randomly chosen password to the user somehow* and then force them to change it immediately the first time they log in.

      Preferably, they should have to log in and choose their new password within a short time period; and where possible, from a previously known location/machine.

    In this way, if your datastore for the encoded authentication tokens is ever stolen, the thieves would have to brute force every single token, because although the encryption method is the same for every token, and they may have also determined the derivation of the salts, the salt is different for each user. Thus they cannot just encode a dictionary of pass phrases with a single salt and search the database to see if any of the tokens match the result.

    Ie. They would need to encode every word or phrase in their dictionary with the derived salt for each and every account. Choose a nice slow encryption mechanism and it becomes too time consuming to bother.


    With the rise and rise of 'Social' network sites: 'Computers are making people easier to use everyday'
    Examine what is said, not who speaks -- Silence betokens consent -- Love the truth but pardon error.
    "Science is about questioning the status quo. Questioning authority". The enemy of (IT) success is complexity.
    In the absence of evidence, opinion is indistinguishable from prejudice.
      Thanks! I figured out most of those steps before the post but somehow overlooked the fact that the unencrypted password will (once confirmed through hashing, with unique salt value) still be available for passing to third-party application in whatever format required. I feel silly not realizing this sooner!


      Greetz
      Beatnik
      ... I'm belgian but I don't play one on TV.
      During my daily commute, I reprocessed my initial requirements and I realized I didn't consider a primary feature. My application will work as a temporary credential store. Exchange with the third-party application is expensive (time) and may not be functional at all times. My intention is to store encrypted credentials for as long as needed (considering low cost sync time and availability) but that could be more than just a few. I have no control on how the third party will take the credentials so I will have to be able to decrypt them. Again, security is something I will take on but the same question remains. Considering I have 20 non-synchronized (encrypted) credentials, Using a on-startup-keyphrase may not be an ideal approach as a keyphrase recovery will invalidate the non-synchronized credentials. Using an external key management solution (whichever approach) can be considered. My target audience might expect some flexibility in how keyphrases are managed so I'll have to look at different approaches.

      Thanks for the feedback!!


      Greetz
      Beatnik
      ... I'm belgian but I don't play one on TV.
        So, basically, it sounds like someone has "solved" their security problem by pushing it off on you. Good luck.
Re: OT: Storing encryption keys securely
by eyepopslikeamosquito (Chancellor) on Jan 25, 2017 at 10:02 UTC

    In case it gives you ideas for improving your security, I'll make some general comments on key management, based on my limited experience in this domain. Ideas, corrections, and feedback welcome.

    Companies with high security needs and big budgets tend to employ Key Management Servers (KMS) and/or Hardware Security Modules (HSMs) to protect their keys. I have some experience with writing client code that uses a KMS. I have no first-hand experience with HSMs.

    The overall strategy is to setup a dedicated and separate physical machine - a Key Management Server - to manage and protect all keys in your system. The KMS is configured to talk to trusted clients only. KMS's can be expensive - and physically isolated if required. Clients of the KMS must supply a set of credentials (e.g. a certificate issued by the KMS vendor).

    • All keys are stored in the KMS.
    • Keys are never stored in client code; they are always fetched from the KMS.
    • Each key has a name and an identifier (id).
    • Client code gets by id when decrypting; gets by name when encrypting. Doing that enables you to rotate the keys on the KMS at any time, and as often as you wish, without affecting client code. Getting by name gets the latest key; getting by id gets the original key (for decryption), even after a key has been rotated on the KMS.
    • Keys are rotated regularly on the KMS - immediately if a key is known to be compromised.

    References

      All of which misses the point. If a client is compromised, an attacker can use its credentials to request any key he wants from the KMS.
Re: OT: Storing encryption keys securely
by eyepopslikeamosquito (Chancellor) on Jan 25, 2017 at 21:58 UTC

    To get a feel for how folks in the cloud are tackling security and key management, I found this AWS security talk by Bill Shinn interesting.

    Some items discussed:

    • Limited Blast Radius. Contain the damage caused by the loss of a single key.
    • Key Hierarchies. Symmetric Key + Master Key -> Encrypted Data Key. You store the encrypted data key with the data. That key is encrypted with a master key that is stored elsewhere. How to protect the master key? Well, you could have an Application Key ... encrypted with a Server Key ... encrypted with a Region Key ... encrypted with an Availability Zone Key, say. That is, design your own key hierarchy - with the goal of reducing the blast radius of the loss of a single key.
    • Auditing. Log key management activity and security-related events to one or more external agents (e.g. via syslog). Important when investigating a breach.

Re: OT: Storing encryption keys securely
by Anonymous Monk on Jan 24, 2017 at 05:32 UTC
    Intranet or Internet... no system is 100% safe... you are describing a problem that does not require a software solution.
Re: OT: Storing encryption keys securely
by Anonymous Monk on Jan 24, 2017 at 19:13 UTC

    Database encryption is largely meaningless because of this problem. Point-of-sale systems sometimes require a human to enter an encryption key to unlock them when they start up, but nobody wants to do that on the web. You might have the webserver switch to an unprivileged user so it can't get the password again after it starts up. If an attacker breaks root on your server, there's really no way to stop them.

    Schneier described a way to address the password-in-memory problem in his book Applied Cryptography. He called it a "boojum"... unfortunately, I can't seem to find a good explanation of it online.

      Boojum is described here.

      Essentially it consists of generating a random number, and xoring the secret data with that random number, and then storing both xored data and the random number in different places in memory. When the secret value is required, xoring the two back together recovers it; but the actual secret doesn't appear anywhere in memory.

      It goes on to suggest generating a new random number and re-xoring once a second, and trying to ensure that both pieces of data are stored on different chips.


      With the rise and rise of 'Social' network sites: 'Computers are making people easier to use everyday'
      Examine what is said, not who speaks -- Silence betokens consent -- Love the truth but pardon error.
      "Science is about questioning the status quo. Questioning authority". The enemy of (IT) success is complexity.
      In the absence of evidence, opinion is indistinguishable from prejudice.

Log In?
Username:
Password:

What's my password?
Create A New User
Node Status?
node history
Node Type: perlquestion [id://1180158]
Front-paged by Arunbear
help
Chatterbox?
and the web crawler heard nothing...

How do I use this? | Other CB clients
Other Users?
Others exploiting the Monastery: (4)
As of 2019-10-16 00:31 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?
    Notices?