SHA256 encoding in javascript - javascript

I am struggling with SHA256 encoding.
There is a Python example but I don't understand it quite well.
Example (Python):
message = nonce + client_id + api_key
signature = hmac.new(API_SECRET, msg=message, digestmod=hashlib.sha256).hexdigest().upper()
Can somebody make a simple blueprint so I can work from there?

Crypto-js implements SHA256
If you include the library, you should be able to run the following (assuming 'message' and 'API_SECRET' are the same as the python code)
var signature = CryptoJS.HmacSHA256(message,API_SECRET).toString(CryptoJS.enc.Hex).toUpperCase();

Related

Decrypting OAEP RSA In JavaScript (Like PHP's openssl_private_decrypt)

I'm currently encrypting data in PHP as follows:
//$sMessage is the input to encrypt.
//$sPublicKey is the public key in PEM format.
openssl_public_encrypt($sMessage, $sEncrypted, $PublicKey, OPENSSL_PKCS1_OAEP_PADDING);
//$sEncrypted will now store the resulting text.
Here's an example of the code used to generate the key in PHP:
$aConfig = array(
"digest_alg" => "sha256",
"private_key_bits" => 4096,
"private_key_type" => OPENSSL_KEYTYPE_RSA,
);
$res = openssl_pkey_new($aConfig);
//$sPassPhrase is the pass phrase.
openssl_pkey_export($res, $sPrivateKey, $sPassPhrase);
//$sPrivateKey is the key (in PEM format).
And my decryption is using a private key that's protected by a pass phrase.
//$sPrivateKeyWithPassPhrase is the protected private key in PEM format.
//$sPassPhrase is the pass phrase to protect the key.
$newRes = openssl_pkey_get_private($sPrivateKeyWithPassPhrase, $sPassPhrase);
//$sEncrypted is the encrypted text (ciphertext).
openssl_private_decrypt($sEncrypted, $sDecrypted, $newRes, OPENSSL_PKCS1_OAEP_PADDING);
//$sDecrypted is the decrypted text (plaintext)
I've also found out how to decrypt with Python using the cryptography library (which you can learn about here):
from cryptography.hazmat.primitives import serialization
from cryptography.hazmat.primitives import hashes
from cryptography.hazmat.primitives.asymmetric import padding
#passphrase is the pass phrase
passphrase_bytes = bytes(passphrase, 'utf-8')
#privatekey is the encrypted private key
private_key = serialization.load_pem_private_key(
privatekey,
password=passphrase_bytes,
)
#ciphertext is the text to be decrypted
plaintext = private_key.decrypt(
ciphertext,
padding.OAEP(
mgf=padding.MGF1(algorithm=hashes.SHA1()),
algorithm=hashes.SHA1(),
label=None
)
)
#plaintext will be the decrypted result.
However, I've been struggling to find a comparable function in JavaScript.
The best answer I found so far was this one: RSA Encryption Javascript
However, it doesn't seem like keys are in PEM format and when I go to the pidCrypt homepage to get more documentation, it's a 404 error.
I found this one as well: PHP's openssl_sign Equivalent in Node JS
The NodeJS library in general seems to have the right functions but when I went through the NodeJS documentation the Quick Start Guide seems to suggest that in order to use NodeJS I have to first install software and set up a web server. According to how to run node.js client on browser, it's not possible "Node.js is not browser javascript. There are many parts of it that use OS features not available in a browser context." (I'm hoping for something I can run in a native browser on the client-side.)
Someone suggested in a comment that I could use WebCrypto. After some struggle to figure out where to download it, I found it's actually native to the browsers (which was a pleasant surprise). However, I haven't been able to figure out how to import a PEM key from the documentation, and when I went to generate a key then export it, the only available formats were "jwk" (some sort of JavaScript object), "spki" (some kind of array buffer), and "pkcs8" (which I only got DOMException: key is not extractable). Nothing looks remotely like the OpenSSL PEM format. (I believe this is PKCS1.)
When I did "crypto.subtle.importKey" it wanted 5 different parameters (format, keyData, algorithm, extractable, keyUsages). None of those accept the PEM string. After a bit of struggle I did find SubtleCrypto importKey from PEM which confirmed that it's possible if you do fancy manipulation to import a PEM public key, however that's for public keys in PEM format and I have no idea how to handle pass phrases (and really I'd rather not program that all by hand). Then I found How can I import an RSA private key in PEM format for use with WebCrypto? and Javascript, crypto.subtle : how to import RSA private key? however those basically told me it's not possible unless I go and convert the private key to PKCS8 using a command line OpenSSL (that also has to be installed separately and I remember was a huge pain to get on Windows). And once I get past that hurdle, I'm still not sure how I would go about getting an equivalent pass phrase protection in PKCS8. I'm hoping there's something similar that ideally supports PKCS1 to do the same as the PHP and Python code above, and I can run it 100% in the native browser. (Importing more JavaScript code is okay.)
I'd ideally like to find a simple working JavaScript example for OpenSSL RSA decryption, equivalent to the PHP or Python ones above. If I have the private key PEM string, the pass phrase, and the cipher text it can give back the plaintext.
Thank you very much! I appreciate all your help a ton and you can save me many hours!
PKCS#1 Versus PKCS#8
Note that while private keys generated without pass phrases in PHP are PKCS#1, the private key generated from PHP with a pass phrase is actually PKCS#8 (see this link for how to determine which standard applies to a private key).
Third Party Library Required
In order to work with PEM-format keys, a custom JavaScript library (or other custom code) is required. There are various libraries at this link which you can look at. Many are not maintained anymore.
This example uses the Forge JavaScript library, but you could also use a different library.
Installing/Importing Forge
While there are various ways to build the Forge environment, the easiest is to add the following HTML code prior to where you need to do encryption/decryption:
<script src="https://cdn.jsdelivr.net/npm/node-forge#0.7.0/dist/forge.min.js"></script>
Performing RSA Decryption
The following JavaScript code will perform decryption using the Forge library with a private key that's passphrase-protected:
// Import an PKCS#8 encrypted key from PHP
//sEncPkcs8Pem = The encrypted PEM key in a string.
//sPassPhrase = A pass phrase string to use for decryption.
//bCipherText = The encrypted cipher text (string of bytes).
var encryptedPrivateKeyInfo = forge.pki.encryptedPrivateKeyFromPem(sEncPkcs8Pem);
var privateKeyInfo = forge.pki.decryptPrivateKeyInfo(encryptedPrivateKeyInfo, sPassPhrase);
var pkcs8Pem = forge.pki.privateKeyInfoToPem(privateKeyInfo);
var privateKey = forge.pki.privateKeyFromPem(pkcs8Pem);
var sDecrypted = privateKey.decrypt(bCipherText, 'RSA-OAEP');
//sDecrypted will store the result.
Full Working Example
The following is a full working example with a 4096-bit key. The JavaScript imports an encrypted private key (PKCS#8 format, PEM encoded) and successfully decrypts a ciphertext.
The encrypted key and ciphertext were both generated using the posted PHP code.
The JavaScript library applied is forge.
<script src="https://cdn.jsdelivr.net/npm/node-forge#0.7.0/dist/forge.min.js"></script>
<p style="font-family:'Courier New', monospace;" id="pt"></p>
<script>
var encPkcs8Pem = `-----BEGIN ENCRYPTED PRIVATE KEY-----
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
ij9mm4GhutigIoP4Wx/NUA==
-----END ENCRYPTED PRIVATE KEY-----`; // 4096 bit key!
// Import an PKCS#8 encrypted key from PHP
var encryptedPrivateKeyInfo = forge.pki.encryptedPrivateKeyFromPem(encPkcs8Pem);
var privateKeyInfo = forge.pki.decryptPrivateKeyInfo(encryptedPrivateKeyInfo, prompt("Enter pass phrase", "testkey"));
var pkcs8Pem = forge.pki.privateKeyInfoToPem(privateKeyInfo);
var privateKey = forge.pki.privateKeyFromPem(pkcs8Pem);
// Decrypt ciphertext from PHP
var ciphertext = forge.util.decode64("lHIspL7aAlnbUdQn6VVY2AS3Ybs/H0fK7N4owfPe6OtzMmX88XOI+2FyEnNyCal6krnfdHYa2JWeWAsyLf484sT2BmvNPxWyYsrnpulKog0lhkeUFppGdhdOHCf7KU47L5p6uYtZmv926ACfhwqMo4M66n/Gkliocol+esavVcfZcjuAw+ELnYkx/TufinR772jBLxVWueGyGcEokI9osDCDpXptmJqpiNRzIrf2kHdk2F/bXRPyE+vrQKFzbyMSpBj3xKtsYDiJ5xDq0qtYY+GCRJNMucPFqOTiFN18EE3z8y/tq5n9Ae/VS8wMxn51rB5JBRmYg3vlM4JLolqNnP3t8OD+DqAeavYjAnairLV0esxzjdkUDpfmFrsYBZWfe5rMzO55drDdsQpGI9LGeX5/TUQpqJWBNZ7QXnbxEiQ2ATXH+ToaeZe3mMkPKuogKM2aEViLzdYB0plbQnoWPAG4OH9pYPGj1KYwdQG5UoF0Ew6Y93uSG3uJ6mcdZZ9gJA0+hpVHOchuAvtZ+vuIV4tzWGfvvnAND54U5sS95EGRj8w/ukgswgOfg/k9iKN3Xlh5N23BYyoLajZVN92cVw6I3XpNOWjlHcO04EhLXaxIeaEMsYYqq3GDBtxpbXfARVjokMeKkKUKNwVscpVneq6WXGtfiMGwXpF8MfoGigE=");
var decrypted = privateKey.decrypt(ciphertext, 'RSA-OAEP');
document.getElementById("pt").innerHTML = "Decrypted: " + decrypted;
</script>
Note: I'd like to give credit to Topaco for their considerable help and original answer, which this one is based off of.

Calling SHA256 with ECDSA algorithm from a Karate script

I am using KARATE with the standalone JAR, version 0.9.5.RC5.
Inside a Karate scenario, I have to sign a string with a private key, using the SHA256 with ECDSA algorithm, in base64.
I need this signature further in a request.
So, I have written in the scenario :
* def stringtobesigned = 'mystringtosign'
* def privkey = 'DeIHYzu9...'
* def Signature = call read('sha256ECDSA.js')
And in the sha256ECDSA.js file, I have written :
function fn() {
var mykey = karate.get('privkey');
var strToBeSigned = karate.get('idstring2signed');
...
return signValue;
}
Can anybody tell me how to implement this algorithm in my use case?
I need to replace '...' with the right code, to the value 'signValue'.
Thanks a lot.

How to handle AES 256 encryption using jmeter?

I am trying to run the script in jmeter but do not know how to handle the AES 256 encryption used for password. Help appreciated.
You can perform whatever encoding operations you want using JSR223 Test Elements and Groovy language via Java Cryptography API, example code for AES 256 encryption would be something like:
import javax.crypto.Cipher
import javax.crypto.spec.IvParameterSpec
import javax.crypto.spec.SecretKeySpec
def textToEncrypt = 'foo'
def secret = 'xxxxxxxxxxxxxxxx'
def cipher = Cipher.getInstance("AES/CBC/PKCS5Padding", "SunJCE")
def key = new SecretKeySpec(secret.getBytes("UTF-8"), "AES")
cipher.init(Cipher.ENCRYPT_MODE, key, new IvParameterSpec(secret.getBytes("UTF-8")))
vars.put('encrypted', cipher.doFinal(textToEncrypt.getBytes("UTF-8")).encodeBase64() as String)
Demo:

NodeJS Express how to unescape HTML entities for display purposes

I am building a web application in NodeJS with Express, Angular JS and Google App-Engine Datastore.
I am learning Node. I created a form that "sanitizes" (escapes) user input before inserting into the database. I followed the NodeJS tutorial on the MDN website to create this code:
//Trim and escape all inputs
req.sanitize('requester').escape();
req.sanitize('requester').trim();
req.sanitize('dataowner').escape();
req.sanitize('dataowner').trim();
req.sanitize('requested_filepath_list').escape();
req.sanitize('requested_filepath_list').trim();
The 'requested_filepath_list' is a list of UNIX file paths.
So when a user submits the request, it is stored in the database in the "Escaped" format.
//Escaped data
/top/example/test123.txt
Question: How can I "unescape" the data for display purposes?
//Desired output
/top/example/test123.txt
I tried the unescape function but it does not seem to work, it just returns the same output.
let escape_str = '/top/example/test123.txt';
let unescaped_str = unescape(escape_str);
console.log('unescaped_str: ' + unescaped_str);
//Output
unescaped_str: /top/example/test123.txt
//Desired output
/top/example/test123.txt
I was able to use the 'he' library to achieve this requirement.
Here's a post with the details: What's the right way to decode a string that has special HTML entities in it?
Here's the library. I was able to install it using npm install.
https://www.npmjs.com/package/he
Example solution:
const he = require('he');
let escape_str = '/top/example/test123.txt';
let unescaped_str = he.decode(escape_str);
console.log('unescaped_str ' + unescaped_str);
You can try this :)
const querystring = require('querystring');
querystring.unescape(escape_str);

SHA1 varies in java and javascript for same input

Facing an issue while creating SHA1 from javascript and java. The problem is both are different. It is used for validating the client request to web server. That means client send a based64 encoded security key to server and server regenerate the same key and equate both are same. Please find below code for generating secret keys in client and server.
Server
MessageDigest mDigest = null;
try {
mDigest = MessageDigest.getInstance("SHA1");
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
}
String input = value1 + value1 + server_key;
byte[] result = mDigest.digest(input.getBytes());
String secret = Base64.encodeToString(result, Base64.NO_WRAP);
...
//comparison logic goes here
...
Client (java script)
var input = value1 + value2 + server_key;
//http://code.google.com/p/crypto-js/
var hash = CryptoJS.SHA1(input);
var encoded = base64Encode(hash.toString());
//WEB SERVICE INVOCATION FROM JAVASCRIPT GIES HERE.
The values value1, value1, server_key will be available in both client and server. The issue we are facing is, the SHA1 generated in both client and server is not matching. I understand the issue is in java its using getBytes() and in javascript using string value for generating SHA1. The CryptoJS.SHA1 does not support bytearray as parameter. We cannot change the server code as it is used by many client applications. Any help will be much appreciated.
In Java ->
byte[] result = mDigest.digest(input.getBytes());
and in JavaScript ->
var hash = CryptoJS.SHA1(input);.
I belief this is the problem. In java the parameter is a bytearray and output is also a bytearray. But in javascript the parameter is var (string) and return is also var (string). I 've also compared the output of CryptoJS.SHA1 with some online SHA1 generating tools. The comparison is true. I am not an expert in this area. If you can explain more, it will be more helpful.
I managed it to do in another way. My application is a cordova based application. So generated the sha1 and encoded it from java and objC and invoked it using cordova plugins.

Categories

Resources