(edit) Still at this. I've changed the code, now using the example functions directly from the library's Github page but am still having the same exact issue. Am I missing something obvious here?? My only deviation is to use the built in crypto_genrichash function for creating the key @ 32 chars (64 was too long). Using their example, created a key too small:
var key = sodium.randombytes_buf(sodium.crypto_shorthash_KEYBYTES),
hash1 = sodium.crypto_shorthash(new Uint8Array([1, 2, 3, 4]), key),
hash2 = sodium.crypto_shorthash('user_password', key);
The link to the raw sodium file https://raw.githubusercontent.com/jedisct1/libsodium.js/master/dist/browsers/sodium.js
And here is the function causing the error:
function RA(A, I, e, B) {
var C = [];
E(B),
A = w(C, A, "ciphertext");
var i, a = g._crypto_secretbox_macbytes(), r = A.length;
r < a && _(C, "ciphertext is too short"),
i = s(A),
C.push(i),
I = w(C, I, "nonce");
var t, Q = 0 | g._crypto_secretbox_noncebytes();
I.length !== Q && _(C, "invalid nonce length"),
t = s(I),
C.push(t),
e = w(C, e, "key");
var o, h = 0 | g._crypto_secretbox_keybytes();
e.length !== h && _(C, "invalid key length"),
o = s(e),
C.push(o);
var p = new c(r - g._crypto_secretbox_macbytes() | 0)
, u = p.address;
if (C.push(u),
0 == (0 | g._crypto_secretbox_open_easy(u, i, r, 0, t, o))) {
var l = n(p, B);
return y(C),
l
}
f(C, "wrong secret key for the given ciphertext")
}
(/edit)
I believe in my attempts to minimize this code for my own learning, I've removed something in the equation of salting or nonce. But, regardless, What I don't understand is that if you run this exactly as is, seems to work, as both console logs show the same exact value of the privateKey both before encryption and after decryption. However, in real world use, the encryption part will be in a separate script, such as a user creation/edit pw page, the new encrypted privateKey sent to mysql for storage (via ajax/php), and the decryption part in the user login script..this is when I get the 'wrong secret key for the given ciphertext' error in the console. But I've checked, and, on the surface, the value ajax returns (note: is in an array with some other confirmations) at authentication is exactly the same as it gets to decryptPrivateKey(result[6], password_normal_input); as when it was first created...at least visually (checked for whitespace in return and password input).
and the sodium package (with the examples) is from: https://github.com/jedisct1/libsodium.js
<script src="components/sodium/sodium.js" async></script>
<script>
window.sodium =
{
onload: function (sodium)
{
function encrypt_and_prepend_nonce(message,password)
{
let key = sodium.crypto_generichash(32, sodium.from_string(password));
let nonce = sodium.randombytes_buf(sodium.crypto_secretbox_NONCEBYTES);
let nonce_arr = sodium.to_hex(nonce);
return sodium.from_hex(nonce_arr.concat(sodium.to_hex(sodium.crypto_secretbox_easy(message, nonce, key))));
}
function decrypt_after_extracting_nonce(nonce_and_ciphertext,password)
{
let key = sodium.crypto_generichash(32, sodium.from_string(password));
if (nonce_and_ciphertext.length < sodium.crypto_secretbox_NONCEBYTES +
sodium.crypto_secretbox_MACBYTES)
{
throw "Short message";
}
let nonce = nonce_and_ciphertext.slice(0, sodium.crypto_secretbox_NONCEBYTES),
ciphertext = nonce_and_ciphertext.slice(sodium.crypto_secretbox_NONCEBYTES);
return sodium.crypto_secretbox_open_easy(ciphertext, nonce, key);
}
var password = 'user_password';
let keypair = sodium.crypto_box_keypair();
let privateKey = keypair.privateKey;
console.log(privateKey);
var privateKey_encrypted = encrypt_and_prepend_nonce(privateKey,password);
var privateKey_decrypted = decrypt_after_extracting_nonce(privateKey_encrypted,password);
console.log(privateKey_decrypted);
}
};
</script>