I have a problem understanding the Blowfish algorithm. I have an app that wants to send login data to the database. The database needs already encrypted password. The database uses php-s CRYPT_BLOWFISH to encrypt/decrypt.
My question is, how can I encrypt the data so it is the same way as php-s Blowfish encryption? I am making apps in Swift, Kotlin and Flutter. I've tried different dependencies that use the Blowfish algorithm ,but they don't output the same hash as php. The php Blowfish is a 60-character string.
The dependencies I've tried:
Dart/Flutter: https://pub.dev/packages/blowfish_ecb
Swift: https://cocoapods.org/pods/BCryptSwift
Thank you in advance.
Expanding on my comment:
You should not be encrypting passwords but rather hashing them. Yes, hashing the same string twice will result in different hashes because of salting. You should not be hashing and comparing in every client you have. If you change ciphers, that’s gonna be a lot of re-factoring for you and your company.
If you have many clients (i.e. mobile apps) then they should be communicating with a web server via an API. For authentication, you should probably look at existing solutions such as OAuth rather than sending usernames/emails and passwords in plaintext over the wire (even with HTTPS).
If you use something like OAuth, once a user has authorised access to the client (i.e. your mobile app) then the OAuth server (your web server) will return an OAuth token that you can store securely in the device’s keychain, and use to make subsequent requests to your API authorised as that user. So this is authentication without a user having to enter any credentials or passwords in your app at all.
Related
I'm building a web service and one of the included features involves storing passwords and credentials for users external applications.
My app is built using PHP/Laravel, the current security measures I've implemented are:
Email and password login accompanied by compulsory two-factor authentication using Google Authenticator
Once users are in they need to type in again a master password to access their database of credentials for their external applications.
CSRF Protection and SSL
The passwords are stored in a MySQL database and encrypted using Laravel's encrypt() method and only decrypted (using the decrypt() method) and given to the user if the authenticated users session ID matches the ID in the row with the password credentials.
When a user requests a password credential is it pulled from the database using AJAX, decrypted and copied to the clipboard then deleted from the client side using javascript so the password is only available for a few seconds on the client side before it's back only in the database encrypted as it was before.
Edit: The key for encryption and decryption is Laravel's app key which is a single key stored in the environment file outside of the visible server files in the public folder.
My application is B2B SaaS and is used by mid-large sized clients meaning it needs to be secure. Please point out any flaws you see in my method or any other advice you think is relevant thanks.
The best way to do this is to not do it.
Put another way: If you can get away with not storing passwords (i.e. using OAuth2 instead), don't store passwords. You don't want the extra liability.
That being said, sometimes you literally cannot avoid storing passwords (e.g. IMAP integrations). In this case, always start with a threat model before you delve too far into the weeds.
If someone hacks your database (e.g. SQL injection), what can they access?
Can they access the filesystem and read the encryption keys?
Can they rewrite ciphertexts from a targeted user's account into the field for an account they already hace access to, and thereby gain access to the plaintext without first obtaining the encryption key?
When a user requests a password credential is it pulled from the database using AJAX, decrypted and copied to the clipboard then deleted from the client side using javascript so the password is only available for a few seconds on the client side before it's back only in the database encrypted as it was before.
It sounds like you're reimplementing a password manager. You might want to shepherd your customers towards something like KeePassXC or 1Password instead.
Since this decryption doesn't include any user-provided secrets, the webserver must therefore be capable of decrypting all of your users' passwords. So if an attacker can hack the webserver, they get all of the users' passwords for free.
If you're dead set on partially reinventing password managers, you're going to want to embrace the principle of least authority and make your server unable to decrypt your users' passwords.
This means using client-side encryption, where your server is a black box that only stores ciphertext.
I'm trying to design a small api however I'm a bit stuck on how to secure the api. I have read some articles about how to do this one of them is: Login and retrieving an apikey and then hash some values with this apikey and send the hashed string back along with the request, so it can be done again on server level.
Is this a good way or is this dangerous to do?
If not miss understood, to avoid man in the middle I can add the request url to the variables that will be hashed, or isn't that the appropriate way
Also my brain is stuck on how to use a time stamp to avoid making lots of request to the same url with same data.
I'm sorry if my question have been asked a 1000 times. However I have read some articles now and it's still not clear to me what way to go for my small api.
From what I have read and understand from it this should be the way.
public key is stored in the application to let the user or application login.
server creates private key for this particular user when it's accessed. Or should this be always the same or a static value that has been created by a person?
user makes request sends along with the request a signature that's hash_hmac(some values+private key);
server checks if these value's are correct and does by creating the same hash from the value's that are send.
If server generates the same hash, the request is valid and can then be executed.
Is this they way to go or am I missing some mayor things here.
For hasing the data is the underneath way a good way to create a hash?
$l_sPrivateKey = 'something returned by database when user loged in';
$l_aData = array();
foreach($_POST as $key => $value){
if($key == 'signature') continue;
$l_aData[$key] = $value;
}
//This should then be the same as $_POST['signature'];
hash_hmac('sha256',serialize($l_aData),$l_sPrivateKey, false);
Your input would be appreciated.
Kind regards and thanks in advance
Secure Remote Password Protocol (SRP6a) With HMAC Fits Your Requirement
The following assumes that your API is browser-to-server so JavaScript-to-PHP not server-to-server using only PHP. SRP will work for both scenarios but the answer below discusses browser-to-server libraries.
Use the Secure Remote Password protocol to authenticate the user of the API which has the side effect of creating a strong session key. You can then use the shared strong session key to sign API requests and responses using HMAC.
RFC5054 uses SRP rather than public keys to create a shared session key to encrypt TLS traffic. There is an implementation in OpenSSL. This demonstrates that SRP authentication is a perfectly safe replacement to public keys to create a secure shared secret. IMHO using SRP is more convenient to solve your problem.
The Thinbus SRP library is a JavaScript SRP library which has a demo of authenticated to a PHP server. The PHP demo does not show using the shared session key but it is simply $srp->getSessionKey() on the server and client.getSessionKey() in the browser once the authentication protocol has finished. The default Thinbus configuration results in a 256bit shared key. You can use this with HMAC see the footnote 1 below about using signed JSON.
How It Works
The registration flow would be:
Client API registration form generates a random API password using JavaScript at the client which is not transmitted to the server. This is saved into the browser local storage and shown to the user asking them to print it off and keep a backup.
The password is given to the Thinbus SRP client JS library code which outputs a client salt and password verifier.
The salt and verifier are posted to the server and saved in the database for that client. Normally Thinbus recommends you keep the verifier hidden by using HTTPS to send the verifier to the server to prevent brute force attacks to recover the password. If you are using a random generated password as long as a typical software license key then you can transmit the verifier over HTTP. See footnote 2 below.
The API usage flow would start with an SRP authentication of the client that has the side effect of generating a session key. Note all this is in the Thinbus demo code as "standard usage" but is explained here to give a flavour of how STP authentication works. This authentication protocol is shown in sequence diagram of the thinbus page and is running in the online demos:
Client javascript loads the API password from browser local storage.
Client AJAX fetches from the server the client salt and a server random one-time number B.
Client javascript generates a one-time number A then uses the password, salt, and both one-time numbers to generate a session key K and hashes that with the both one-time numbers to create a password proof M that it posts to the server along with its random A.
Server uses the password verifier saved to the database at registration, the client salt, and the two random numbers to compute the session key K then confirms the client sent password proof M is good. If that is all good it sends its own proof M2back to the client. At this point the client has been authenticated using STP as a zero-knowledge proof of password.
Client checks M2 against its computation. If all is good both sides have a shared secret K which is a one time 256 bit session key derived from the random A and B that no man-in-the-middle can feasibly know.
All API requests and responses can be HMAC signed with the shared secret and verified on the other side.
All of the above is covered in the PHP demo of Thinbus minus actually calling $srp->getSessionKey() at the end to have a key that can be used to sign things with using HMAC.
Give that SRP replaces password authentication with a cryptographic zero-knowledge proof of password it is surprising that not all developers use it by default. The fact that it also generates a shared session key for API signing is simply an added bonus.
Footnote 1: Most APIs would prefer to post one JSON value with all the data in it. This is because JSON is simple yet more powerful with built in API in both PHP and JavaScript to turn objects into strings and back again. As #dbrumann pointed in a comment there is a standard for signing JSON which is JWT. Google suggest that here are libraries for this in both PHP and JavaScript. So if you upgrade to passing one JSON input value and returning one JSON output for every command in your API Ayou can use a JWT library to sign and validate the JSON inputs and outputs of the API. One of the JWS algorithms is "JWSAlgorithm.HS256 - HMAC with SHA-256, 256+ bit secret". The libraries will sort out the mechanics of actually signing and verifying so you don't have to write that code and worry about possible security bugs.
Footnote 2: The recommendation with Thinbus is to transmit the password verifier to the server over HTTPS to keep the verifier secret. This is to prevent interception then an offline dictionary attack against the password verifier to recover the password (i.e. the password is salted into the verifier so you would need to run the 16G crackstation password dictionary through the verifier generation code with the user salt to find a match). With API usage the browser window.crypto API can generate a truly random "API key". Typically windows keys were 16 upper case letters shown to the user formatted as XXXX-XXXX-XXXX-XXXX. Checking the GRC password search space page it says that a random 16 letter upper case password that size would take a government 14 years to exhaustively search. Given that estimation you can safely transmit a password verifier generated for such a long random password over plain HTTP without encryption as no-one will feasibly dedicate many years of computing power to run so many password guesses through the verifier generation algorithm (which uses the random client salt so cannot be pre-computed) to find a match to recover the client API password.
I am currently working on a mobile app that has a accompanying web service being developed in PHP. The one thing that we want to make sure is that the users data is safe in every possible way.
After careful evaluation, we have decided to use RNCryptor for all things related to encryption. This is in addition to the HTTPS connection. The current process is like below (login example):
The RNCryptor library on iOS uses a key to encrypt password before sending it to the server.
The server then stores this encrypted password on the database.
While re-authneticating, the app sends the password (again encrypted with the static key) and the server decrypts it (means the server also has the encryption key), verifies the login and sends the login key (encrypted with the same static key) back to the client.
Every subsequent request relies on the encrypted loginKey and the username for authenticating the validity of the user and login session.
I believe the above system is flawed because of the STATIC encryption keys and since the key is available on both the server and the client.
What we would like is to make the encryption key dynamic by merging the raw password with the STATIC encryption key. This would make encryption key unique for each user but it also means the server will have no idea about the key. It is essential for the server to know the key since other user data also gets encrypted and decrypted based on this key.
Can somebody help me out with this? What steps do I need to take to make the system more secure? Any code snippet or reference link specific to server-mobile client would also do. I know there are a lot of tutorials out there but mostly all resume the client to web based and not mobile.
PS: Sorry for such a long post.
I would probably just use OATH2 tokens for authentication, but if you wanted to do it your own way...
For securing passwords a salted hash is used. As a basic example of hashing passwords with a salt consider the following, and keep in mind it's NOT cryptographically secure.
shaResult = SHA1(16 Byte Random Salt | "p#ssword")
Basics: The server stores the shaResult. Your app stores the salt value generated. When the user types in their password you append it to the stored salt, hash it, and send it to the server for verification. There's really no need to encrypt it to the server now. The HTTPS connection should handle that.
Good cryptographic password hashing is described in detail at Salted Password Hashing - Doing it Right To summarize they suggest using the following:
Salt should be generated using a Cryptographically Secure Pseudo-Random Number Generator (CSPRNG). Suggested CSPRNGs is given in the link for multiple programming/scripting languages.
The salt needs to be unique per-user per-password. Every time a user creates an account or changes their password, the password should be hashed using a new random salt. Never reuse a salt. The salt also needs to be long, so that there are many possible salts. As a rule of thumb, make your salt is at least as long as the hash function's output. The salt should be stored in the user account table alongside the hash.
Use a well-tested cryptographic hash algorithm, such as SHA256, SHA512, RipeMD, WHIRLPOOL, SHA3, etc.
Use slow hashing functions that perform multiple iterations. Standard algorithms include PBKDF2 and bcrypt.
Use a keyed hashing algorithm, HMAC.
I'll reiterate that secure connections still need to be used in conjunction with the above.
If you want a method that does not use the same authentication value each time consider using the Challenge-Handshake Authentication Protocol which protects against replay attacks. See RFC1994 for more complete details.
At setup a shared key is established between the client and server. This must be done securely, possible with SSL or side-channed communications.
Authentication:
The server sends a random challenge to the client.
The client uses the challenge value to compute a hash with a function such as PBKDF2 and sends it to the server along with the user identifier.
The server performs the same computation and verifies the value from it's user identifier/shared key table.
There are slight variations but the concept is the same.
I am currently building a web/desktop application. The user can create an account online and login either online or via the desktop client.
The client will be built in Python and exported to exe.
I want to encrypt the password before it is sent online as the site has no https connection.
What is the best way to do this so the hashed password will be the same in python and php? Or is their a better way or should I just invest in https?
I have tried using simple hashing but php md5("Hello") will return something different to python's hashlib.md5("Hello").hexdigest()
Forget this idea. Hashing the password on the client, sending the hash to the server and then compare it to the stored hash is equivalent to storing plain passwords in the database, because the hash becomes the password.
Or should I just invest in https?
Yes!
Can you share a code example to reproduce this, along with the two different outputs ?
They should, and do, create the same output.
You should also either use HTTPS or look use a challenge response mechanism ( here's an example that many mail servers use : http://en.wikipedia.org/wiki/CRAM-MD5 )
Encrypting the password has no security effect - anyone can intercept the password and re-use it. The password remains secret, but anyone can still login as if they know it.
I am developing an iPhone app that needs to use a Joomla-generated database located on my own server.
There are a lot of solutions, so for more security I decided to 'talk' with the database via PHP.
I have a PHP page like this:
www.mypage.com/iphonelogin.php ?username=USER1&password=XXX&option=login
The option can be: getuserinfo, login, reset password, etcetera.
The problem is that the password stored encrypted in the database. (MD5(password+Salt):Salt)
So, I am wondering how to do this the following ways:
Low security way: PHP gets a plain text password from the APP and the Full encrypted password from de DB. Then PHP uses the salt, encrypts the password and does the comparison, then return YES or NO to the APP.
Other way: PHP gets the password REVERSIBLE encrypted from the APP and decrypt it, then the same like above.
Nice security way (pretty slow): PHP get the Full encrypted password from the DB, then shows the Salt to the APP. The APP encrypt the password Joomla way and send a full encrypted password to PHP which do the comparison and returns YES or NO to the APP.
I need high security and fast connection, because every time the app needs something from the database, the login must be confirmed.
Please tell me what to use or some another way to do it.
You should be writing a session management feature set into your client <=> Joomla server setup.
This workflow would see the user only enter email and (plain) password once and then request the session token from the server.
This token could be then validated each time the client requires data from the server.
As you have noted, never expose the database directly to the client. That is just a bad idea for any setup. You should always keep an interface/API buffer between the client and server abstracting away potential security risks.