Is it safe to put secret in the rippled sign command - ripple

in the rippled api document https://ripple.com/build/rippled-apis/#signrippled sign
For the sign command, there is an optional parameter 'secret',
I have a conern, if it is presented, is it safe?

As documented in your link:
Caution: Unless you run the rippled server yourself, you should do
local signing with RippleAPI instead of using this command. An
untrustworthy server could change the transaction before signing it,
or use your secret key to sign additional arbitrary transactions as if
they came from you.
So if it is just safe when you are calling this method on your own server. You should never call this command and send your seed, secret, or passphrase to a public server.

Related

How does a server verify a JWT? Where does the Public Key come from?

I am looking at the examples of JWT tokens in Node.js, and the verify function. My question is, where does this publicKey come from in verify(token, publicKey)? What is the flow?
The client (one of my users) has a client library installed on their computer/server, for making requests to my app myapp.com. In the myapp.com server, I call verify(token, publicKey). In the client library I generate the token using privateKey. The question is, how does the client get this private key generally? (i.e. is heroku login downloading a private key under the hood for making JWT requests, sort of thing?). And how do you fetch the public key? My understanding is, the client would download a private key, and our server would store the public key. Then given you have the public key and token, just call verify(token, publicKey). But how do you get the public key for the token on the server generally? Is the server storing one public key per private key disseminated to the client installed libraries?
The way I've usually seen JWTs used, there is only a very small number of trusted issuers, often only one, and the tokens are used as bearer tokens. In many cases, the issuer and the verifier are the same. In other cases, the verifier trusts one identity provider (e.g. Google) and fetches the public key from a https URL (example).
In your case, you could act as both the issuer and verifier:
You (the server) would generate one key pair.
Your API servers would trust JWTs signed by this key (and they'd only have the public key, since they only need to verify them).
An authentication/management server would have the private key, would authenticate your user, and issue them a JWT.
The client would never handle any keys, they'd simply store the signed JWT, and pass it as a bearer token when making a client request.
This is e.g. the approach described here as the approach used by GitHub. In this case, the issuer and verifier both belong to you. This approach is the easiest for both you (you can trust the content of the JWTs once you've verified the signature), and the client (they're just dealing with an opaque API key and don't need to deal with the complexities of JWTs at all).
A possible alternative approach could be:
A key pair is generated and the public key is associated with the account. This can be done in multiple ways (see below), but the end result is the same: The client has a private key, and your server knows the corresponding public key and which user it is associated with
When making a request, the client creates a JWT, signs it with its private key, and includes their user name in the token (e.g. in the iss and or sub field).
Your server takes the token, extracts the user name, looks up the public key associated with the account in the database, and validates the token.
This approach is used e.g. by Google Cloud for service account authentication.
Step 1 above can be done in two ways:
You authenticate the user, generate a key pair, associate the public key with the account, and let the user download their private key (via https of course). While it's generally considered somewhat bad form to generate keys for someone else (because you get to see a key that you don't need to know and you have to send it over the network), it's a lot easier, and Google is doing just this.
The user generates and stores the key pair. You authenticate the user, the user uploads the public key, you associate it with the account.
Either way, if you go with the "user signs a JWT" approach, you likely will want to provide client libraries, or at least code examples. Note also Google's requirement that the tokens must be short-lived, enforced by treating long-lived tokens as invalid. Without this rule and enforcement, what will happen is that many client developers will be annoyed about your complicated solution, manually sign a token that is valid forever on his laptop, and then use it as a bearer token.
heroku login actually doesn't use JWTs at all. It retrieves and stores an OAuth Bearer Token. This is most comparable to the first approach (client never handles any private keys, just gets an opaque blob, which happens to be a JWT that you can verify). The difference between a non-JWT token and a long-lived JWT is that your API servers have to look up the meaning and validity of the regular token in a database, whereas the JWT directly tells you the user identity, and possibly permissions and other attributes that you included when issuing it.

JWT with user password in key

I want to use JWT in my application.
Now I'm wondering if it is secure to use the users password in combination with a private secret as a key to sign my tokens. This way, tokens get invalidated if a user changes his/her password.
But maybe it makes my private secret vulnerable?
Thanks for your thoughts on that!
The secret is a preshared string exchanged between the client and the server.
So in your case:
SecretString= PresharedSecret + ClientPassword
So, everytime the client passes a JWT token, you would need to retrieve the password from the database or have some way of preloading it and a check in case of password changes for validating the token.
This might lead to the following scenarios:
Everytime the client forgets his password, you might need to make database calls that can be expensive
It would enhance security in one way, as anyone who changes the password will not be able to communicate with the server with knowledge of the previous SecretString.
A new preshared secret will need to be decided.. and validated with the new registered password.
Overall, it does increase security. However, it depends on the purpose or the usage of the infrastructure. If it is a system in which users frequently forget passwords.. this might not be a great option.
The usual thing is to sign all the tokens with the same key. Simplifies the management and avoids querying the database in each request.
Signing with a key+user password is feasible and has the advantage of allowing to revoke tokens (with the commented drawbacks).
Ensure that your signing key is enough secure deriving it from user's password and has the recommended length of the selected signature algorithm. Do not store or use user's password directly.

Is this a safe way to do two key encryption to store a third party password?

I'm building a system that connects to a third party api, and I have to store passwords for each of our users connected to that api. I need to make sure that the passwords are stored securely, so I don't want to trust the user's password as an encryption key. But I also need to make sure that we need the user to authenticate the use of this password, by entering their password.
I had the idea of creating a key by combining the user's id and password with a secret key on the server (just by concatenating them all). I then use crypto's createCipher with aes256 and the new generated key to encrypt the third party password and send it off to storage.
I noticed the text in the createCipher documentation that says this:
In line with OpenSSL's recommendation to use pbkdf2 instead of EVP_BytesToKey it is recommended that developers derive a key and IV on their own using crypto.pbkdf2() and to use crypto.createCipheriv() to create the Cipher object.
And I read up about IVs and the attacks they are meant to prevent (still pretty confused about how that works, especially with my use case) but I think that since this will technically be using a different key every time, that will be a non-issue.
Is this kosher? Is there some vulnerability of this system that I'm missing?

How to secure webhook identity

I am developing a service where customer can register their webhook URL and I will be sending updates on the registered URLs. For the sake of security, I want to let the client (receiver) identify that its me(server) who is sending them the request.
Facebook and Github both sends a X-Hub-Signature containing the hash of the payload prefixed with a secret key.
I can follow the same strategy. But what if I simply use jwt:
On registering the webhook I share a secret key with the client.
Then in each webhook request I will be sending a jwt computed using the same secret key.
I don't know much about cryptography, but the jwt approach seems more efficient as I don't have to compute the signature again and again because I am not using the payload in the signature.
But then why both Facebook and GitHub follow the other approach?
The content on this site may be out of date. For the most accurate and up-to-date content, visit
Using a MAC (Message Authentication Code) allows one to authenticate a message, as implied by the name. Sending a secret with every message is not wise, as this is likely to result in the secret being compromised. An attacker might intercept one of the messages and then start issuing spoofed messages.
Another thing which you might want to consider is replay attacks. What if an attacker intercepts a message and sends the same message later?
Edit: Using JWT is fine, as it includes a MAC, but you must make sure that the payload is authenticated (i.e. included in the computation of the MAC).

security - how to secure api key in HTTP GET request

I'm new to cryptography and I'm trying to prevent against man-in-the-middle-attack in a web service I'm developing. The way the web service work is that a user registers on the service using his email address and password and creates an application. Each application is given an application id and an application key. The application id is public (that's how the public communicates with that application) but the application key is private. The user credits his application by loading a pin (a 16 digit numeric string). Loading the pin is done via a HTTP Get request.
Now here is my question: how can the user do a HTTP GET request with his application id (the way the server identifies the application) and his application key (the way the server authenticates him) without compromising his application key?
Because our server has SSL (and I read that SSL protects against man-in-the-middle-attack), I was thinking about simply having users submit their application id and application key as parameters in the GET request, but after reading around, I decided this may not be secure. This is also because after doing the HTTP GET request to load the pin, the user may configure his account that we submit the server response via another HTTP GET request to a URL of his choice. And since we want to do an echo back of his application id and application key so he can authenticate that the request was really from us, I was worried his key might be compromised.
So I decided we should have the user do a md5 hash of his app id and app key to provide a hashed parameter and submit that instead of his app key in the GET request. Then on our server, since we already know the user's app id and app key, we can simply do an md5 hash of both and compare it with the hash parameter the user submitted. But then I also thought that may be insecure because if someone intercepts the hash parameter, the attacker can use that same hash parameter to submit several requests since the app id and app key is static. So in the long run, the hash parameter is no different from the app key.
Now I'm thinking, we should have the user do a md5 hash of his app id, his app key and the pin he wants to load to get the hash parameter. This way, since the pin is always different each time, even if an attacker intercepts a request, the authentication process would not be compromised for other requests because the attacker would not be able to reuse that hash with other requests.
For example, if a user has the following credentials:
1. app_id: 1234
2. app_key: bghuTHY678KIjs78
And a user wants to load the pin: 1234567890123456
He generates the hash by doing an md5 hash of "1234:bghuTHY678KIjs78:1234567890123456". That gives him 210a4c92d85473af9d5f48b4ee182ddd. Then he does a HTTP Get request to the address below:
https://example.com/process?app_id=1234&pin=123456789012&hash=210a4c92d85473af9d5f48b4ee182ddd
Is this method secure? Or should I simply just have the users submit their app id and app key in the HTTP GET request since we have SSL?
The user secret should never be sent over the network. Instead, ask the user to sign his requests using his secret. HMAC is the relevant algorithm.
By the way, MD5 is obsolete and insecure for all crypto needs.
Use Secure Remote Password (SRP6a) and register a password verifier and salt for the 16 digit pin. The pin you never send to the server (you can store it in browser local storage for convenience of the user). Then authenticate the client using SRP6a which results in a strong shared secret session key for each successful authentication. Then use HMAC SHA256 to sign API calls using the session key. See the thinbus-srp JavaScript library and its demos of using SRP6a to authenticate resulting in a session key. See the JWS "HS256" (HMAC with SHA-256, 256+ bit secret) algorithm and any library implementing that as an example of signing a web API with a shared secure key.
The SRP6a authentication protocol is a secure zero-knowledge password-proof where the server does not know the password. The server issues a random challenge to the client which generates a password-proof based on the challenge. The server uses the verifier the client provided for their password to check the password-proof. If the 16 digit pin uses uppercase letters like a standard software license key it is infeasible to run a dictionary attack on the verifier. Use the modern browser webcrypto secure random number generator to generate the pin at the browser. Even you won't be able to obtain the password.
The overhead of using SRP6a to authenticate is that you need the client to first fetch the server challenge. The benefit for your use case is that if the client provides a good password-proof based on the challenge the both the client and server share a secure session key. No-one intercepting the traffic can know the session key. With that shared secret you can sign and verify every API call and verify the signature at the server. No-one intercepting any part of any exchange between you and the client end-to-end from registration through to usage can gain any advantage.

Resources