Difference between RSAwithSHA256 and SHA256 - javascript

I need to sign XML SAML message with the SAML 2.0 standardised algorithm (RSAwithSHA256). But my saml plugin (passport-saml) only seems to support sha1 and sha256. The SHA256 sounds pretty close to RSAwithSHA256, but probably is not the same thing? What is the difference, and how could I use RSAwithSHA256 instead? I probably need to edit the passport-saml library, to allow the use of RSAwithSHA256 algorithm?

I try to explain the differences, but not how to solve your issue.
RSA is a Public Key Cryptographic algorithm (Public and Private Key-Pair algorithm) and it assures Confidentiality, Authenticity (includes Identification) and Non-Repudiation.
SHA-256 is a Hashing algorithm, that produce a unique, fixed size 256-bit (32-byte) hash and it assures Message Integrity.
Hashing algorithm employed as follows,
Sender sends message and its hash to receiver. [Hashing employed]
Receiver hash the message to generate new hash. [Hashing employed]
Receiver check whether the new hash is equal to original hash.
If its equal, then message integrity is confirmed and receiver process the message further.
If its unequal, then message is tampered and receiver discard the message.
Here, how receiver confirms that message and its hash are indeed sent by expected sender? There is no authentication or identification of sender by receiver in the above case.
To do that, we have to use both Public Key Cryptography and Hashing Algorithms (like RSAWithSHA256) together to satisfy the above said requirement.
So, when employ Public Key Cryptography and Hashing Algorithms together,
Sender sends message and its encrypted hash (using private-key of sender) to receiver. [Encryption and Hashing employed]
Receiver decrypt the encrypted hash (using public-key of sender). [Decryption and Hashing employed]
Receiver hash the message to generate new hash. [Hashing employed]
Receiver check whether the new hash is equal to decrypted hash.
If its equal, then message integrity, authenticity and
identification of sender is confirmed and receiver process the
message further.
If its unequal, then message is tampered or not sent by intended
sender (since encrypted hash is not generated with private-key of expected sender) and receiver discard the message.

Related

Is there a way to encrypt a file/string using public/private keys generated by Hyperledger Fabric?

I am using Hyperledger Fabric V1.4 on my project. I have enrolled and registered users. And now I want to transfer files between users while remain private, which means I need to encrypt the file so that only the receiver can see. For example, user A wants to send a file to user B. The basic workflow I'm thinking right now is that:
User A and B register in the Hyperledger Network and get public/private keys.
User A uploads a file in IPFS and gets a hash from IPFS. (Since everyone with the hash can access the file, we need to encrypt the file hash.)
Encrypt the file hash with user B's public key.
Send the encrypted hash to user B.
User B receives the encrypted hash and uses B's private key to decrypt the hash, and gets the IPFS file hash. Then B can view the hash using IPFS.
Problems I'm having:
In step 3, how to get a user's public key? I only found ways to get certificate and private key. Or can I get public key from the certificate?
Is there an algorithm to encrypt files/strings using Hyperledger-generated public and private keys?
Thank you!
Yes it is possible something similar, but with ECDSA it does not work this way. You do not encrypt with the user B's public key. What you do is to derive a symmetric key from user B's public key and user A's private key in a way the same symmetric key is derived from user A's public key and user B's private key. It is known as ECDH. I haven't here an example in Javascript (you can search it the same way I would), but to understand it, take a look a give a try to the example (with OpenSSL) in https://jameshfisher.com/2017/04/14/openssl-ecc/.
You can get the public key from the certificate (it is embedded in the certificate) or derive it from the private key. Choose your way.
NOTE: I find more secure encrypting the content before storing it in IPFS and share the hash than encrypting the hash.
EDIT: For nodejs, you can try this: https://www.npmjs.com/package/eccrypto. It seems it includes also some similar to what you were looking for initially.

Is my security design sound?

I have a specific need for security which means I'm writing more security-related code than I'm comfortable with. If what I'm doing is solved by a library somewhere, please, let me know and I'll drop my implementation immediately.
I have a server written in Java (actually Clojure) and a client written in JavaScript (actually ClojureScript) that runs as an Electron application. I need various clients applications to exchange information through the server ever being able to access that information: I need end to end encryption.
To implement end-to-end encryption I want to have a private public key-pair generated in the client and then the public key and an encrypted version of the private key will be uploaded to the server. Then, by doing a sort of challenge response in which the client signs a piece of random data and the server verifies it, the server would authenticate the user.
The registration process includes generating an Elliptic Curve Diffie Hellman key pair, specifically, P-521 (secp521r1) which seems to be a good choice according to https://security.stackexchange.com/questions/78621/which-elliptic-curve-should-i-use
After generating that, generate a 16 byte salt and then I pbkdf2 the password 872791 times with that salt, with a keylen of 32 and using sha512. Using the hashed key I encrypt the private key with aes-256-ctr. The last step is concatenating the salt length, the salt and the encrypted private key and send it to the server.
I'm assuming all of this happens over a TLS-secured channel, HTTPS, in which the validity of the certificate of the server is verified in the usual way, through the CAs. In the future I might use certificate pinning to increase security.
Is this a sound design? Does it look secure? Is there any or all of this that I could just delegate to a third party open source library that is well maintained?
My actual code:
(def elliptic-curve-name "secp521r1") ; https://security.stackexchange.com/questions/78621/which-elliptic-curve-should-i-use
(def encryption-algorithm "aes-256-ctr") ; http://lollyrock.com/articles/nodejs-encryption/
(def hash-bytes 32)
(def salt-bytes 16)
(def pbkdf-digest "sha512")
(def iterations 872791)
(defn encrypt-text [text key]
(let [salt (.randomBytes crypto salt-bytes)
salt-string (.toString salt "base64")
hashed-password (.pbkdf2Sync crypto key salt iterations hash-bytes pbkdf-digest)
text-cipher (.createCipher crypto encryption-algorithm hashed-password)
encrypted-text (gstring/format "%04d%s%s%s"
(count salt-string)
salt-string
(.update text-cipher text "utf8" "hex")
(.final text-cipher "hex"))]
encrypted-text))
(defn decrypt-text [encrypted-text key]
(let [salt-length (js/parseInt (subs encrypted-text 0 4) 10)
salt (.from js/Buffer (subs encrypted-text 4 (+ salt-length 4)) "base64")
hashed-key (.pbkdf2Sync crypto key salt iterations hash-bytes pbkdf-digest)
encrypted-text (subs encrypted-text (+ salt-length 4))
text-decipher (.createDecipher crypto encryption-algorithm hashed-key)]
(str (.update text-decipher encrypted-text "hex" "utf8")
(.final text-decipher "utf8"))))
(defn generate-key-pair [password]
(let [diff-hell (.createECDH crypto elliptic-curve-name)
public-key (.generateKeys diff-hell "base64")
private-key (.getPrivateKey diff-hell "base64")
encrypted-private-key (encrypt-text private-key password)]
[public-key private-key encrypted-private-key]))
This is an excellent start. These kind of questions are tricky and there is no way to prove these things secure. There are some good conceptual "pillars" to guide ones thoughs on it:
The pillars of security:
Privacy:
This code does not provide it. An attacker in the middle can read the structure of the message and can understand almost all of it. This gives them a strong stance. This system is open to replay attacks.
Authentication
By matching the password hash you are giving a strong assurance that this person does indeed know the password. PBKDF2 with a salt is state of the art and looks like you have this down.
Integrity:
This code does not provide it. the public key could be changed in flight. An attacker can substitute their own public key and cause the system to generate messages that they then could read. This attack is dependent on the rest of the system to detect the breach and respond to it, by comparing the public and private keys. This could open the system to known or unknown crypto attacks by allowing a "chosen key attack" which is generally considered dangerous. You really need to assure the integrity of the entire message. An attacker can take a password and key they do know along with a private key they do know, and switch them. Combined with replay attacks this will likely break the system.
Suggestions:
The structure of the entire message must be authenticated. There are two approaches to this. Either use a keyed MAC (Message Authentication Code) or use an "Authenticated Encryption" algorithm. MACs are included in more of the common crypto libraries. Don't roll your own MAC, and don't try to use a hash for this.
The privacy of the message should be ensured. This can be accomplished by ensuring that The message is send over TLS (you may already be doing this).
the message must include protection against replay attacks. This can be done in many ways. One strong way is to use a NONCE (Number used ONCe) so the server will only ever accept each message once. This must not be "per user" because many replay attacks are cross user.
The part you are absolutly doing correctly is asking for public scrutiny early in the process. This puts you way ahead of the industry norm. remember that
"Anyone, from the most clueless amateur to the best cryptographer, can create an algorithm that he himself can't break."
https://www.schneier.com/blog/archives/2011/04/schneiers_law.html
EDIT: make sure the password that protects them from you guessing their private key is not the same password you use to authenticate them (and that there is no way for them to use the same password)

JavaScript message system encryption

I'm trying to create a message system with JavaScript and PHP / MySQL. I have a form with two input elements (recipient id, message content). I'm using MVC (Zend Framework 1). The form post data is send to my controller and stored in the database.
Now I want to encrypt the message before it is sent. I want to keep it user-friendly, so my idea was to use RSA (private / public key). The idea was that a private key was generated on user log in and stored in the cookies, to make sure that the private key is only on the user's machine. The public key could be stored in the user's table, so that any user, who want to send a message to him, can encrypt the data.
It is important that the key-pair is generated by the user's password. If it's random generated, it would not be possible to use multiple systems to log in, because the private key would change everytime. So that would be the mechanism to make sure, that he will always have the same private key, until he is changing his password.
I tried a few JavaScript libraries. cryptico seemed to be the right choice, because it generates private / public key by password. The problem here is, that I can not store the private key and not even look into the value.
They have an example on the website
// The passphrase used to repeatably generate this RSA key.
var PassPhrase = "The Moon is a Harsh Mistress.";
// The length of the RSA key, in bits.
var Bits = 1024;
var MattsRSAkey = cryptico.generateRSAKey(PassPhrase, Bits);
When I try to output MattsRSAkey, I only get [Object object]. It's the same when I store it in the Cookies. I tried to use JSON.stringify. With this function I can store and look inside MattsRSAKey. But when I want to use it later to decrypt the message, I get an error, that I have no valid public key. I think the private key got broken while storing it. When I read the private key from Cookies I use JSON.parse.
Is there any way to solve my problem? I just want to send encrypted messages from multiple users (public key) to one user (private key). My intention is not to have a secure transport but to store the messages encrypted in the database, so that unauthorized persons can not read it. It is important that I do not only have encryption for one-to-one messaging. This would be easy, because both users only would need to share a password for encryption.
There's a couple of things wrong here.
First, you're trying to store a Javascript object directly in a cookie. This won't work: cookies can only store string values. You will need to serialize the key to a string to store it in a cookie; unfortunately, it doesn't appear that the cryptico library exposes any methods to do this, so you will need to either implement a custom serializer, or use another cryptographic library.
Second, you are storing private cryptographic key data in cookies. This is perhaps the worst possible place to store this, as cookies are sent to the web server on every request. Local storage is much more appropriate here, as it is only accessible from Javascript code.

How to add HMAC to CryptoJS AES encryption?

CryptoJS's convenience function CryptoJS.AES.encrypt("some plaintext", "password") doesn't seem to do any authentication.
I see CryptoJS provides an HMAC class, but I'm confused about how to use this to encrypt-then-authenticate.
I searched around for tutorials and other questions but couldn't find any.
How would I add authentication using the above CryptoJS HMAC class to authenticate the ciphertext produced by CryptoJS.AES.encrypt?
The idea with the HMAC provided by cryptoJS is to have you, the developer, pass it both the encrypted data and a key in order for it to spit out the MAC on the other end.
Below is an example of how you could use it to produce a MAC for your encrypted data. The idea here is that the key object is the shared secret used between you and trusted parties to verify the integrity of the encrypted data.
//Encrypt Data
var encryptObject = CryptoJS.AES.encrypt(content, key, { iv: yourIV });
//Calculate HMAC
var HMAC = CryptoJS.HmacSHA256(encryptObject.toString(), key);
A few things to keep in mind.
Always calculate the HMAC on the encrypted object before decryption. This prevents any manipulation of the encrypted data to cause harm after decryption.
Make sure the data encoding/format is the same when validating the HMAC. For example, above I used the toString() of my encrypted object, I did this becuase cryptoJS automatically serializes that object to only be the ciphertext. Upon decryption, I calculate the HMAC on the binary string of the encrypted blob I am presented with to make sure the HMAC calculates correctly.
With that I think you should be set to validate some data!
Also for a working example, you could check out http://meowcrypt.com/ which is my in browser file encryption service for google drive that uses cryptoJS.

Simple XOR a message (Javascript/Tcl)?

I need the username/password to be scrambled at the client-side before sending it over via HTTP GET/POST. And the server will decode it with Tcl, before the checks against database.
Currently I'm thinking about using JavaScript for the client-side. Java Applet will also do.
Is there any way, that I can easily achieve it, using Simple XOR or any other methods? (Examples would be much appreciated)
I've found the few samples in C/Python/.NET/Java... But not in JavaScript and Tcl.
SSL is not an option to use, sadly.
If ssl is not an option, then I suggest the following scheme, which many sites use instead of SSL:
On the client side, combine the user name and password, then calculate a hash from it (MD5 is a popular choice).
Send the user's name and hash over to the server
On the server side, retrieve the password for that user from the database.
From the user name and password, calculate the hash and compare it with the client's hash. If the two match, then the passwords match.
For added security, add a little random text to the user+password mix. This random text, AKA the "salt", must be known on both the client and server sides.
Here is a suggestion on how to calculate the hash using MD5:
package require md5
proc calculateHash {user password salt} {
return md5:md5 -hex "$user:$salt:$password"
}
How to use it:
set user "johnny"
set password "begood2mama"
set salt "myDog_is_meaner_than_yourDog"
set hash [calculateHash $user $password $salt]
superNobody,
You should consider alternatives to storing plain-text passwords in the database. See:
http://www.codinghorror.com/blog/2007/09/youre-probably-storing-passwords-incorrectly.html
Instead of encoding the password in Javascript, then decoding the password in Tcl to compare with the database, you should consider SHA1 hashing in Javascript, and storing SHA1 hashed values in the database.
There are several available examples of a SHA1 hash function in javascript (just Google 'sha1 javascript'). The tcllib Tcl library has SHA1 support.
As HaiVu mentioned, you should also consider hashing / storing more than just a straight password hash, but instead use something like SHA1( username + websitename + password ). You can calculate this on the client in Javascript, and store it in the db.

Categories