I want to encode a number which would be maximal 10 digits long using a key with ASCII chars.
The encoded string should be decodable with the same key , which should return the decoded number.
10 => encoding_with("secret_pass") => hash => decoding_with("secret_pass") => 10
Both operations should work the same way in Javascript and Ruby.
What algorythm should I use for this purpose ?
All data should be in ASCII, no multibyte data for input, hash, and the key.
A simple XOR should be sufficient.
JavaScript
Ruby
Yes, you can go overboard and break out the full crypto suite, but since one part of the algorithm will run in-browser, in JS (completely untrusted environment), any attempt at Serious Cryptographyâ„¢ will give you a false sense of security (in other words, will actually make your system less secure).
If you're trying to protect the data in transit, use the tool that's made for the job; in this case, HTTPS.
I would look into some for of a Symmetric Key Encryption, and the most prominent one AES. AES is pretty much the standard and is implemented in both languages. Just make sure to use the same key and salt for encryption and decryption.
Javascript AES
Ruby AES
If you want it to be simple, and security isn't a great concern (since the javascript... observation in the comments), the easiest way would be to simple generate any random value, bigger (more digits) than the number, and simple XOR it with the number. This assumes the key (=random number) would be previously shared with the other program.
1. generate random number with 10 hex digits -> KEY
2. take the number then do (number XOR key ) -> result
3. send result
4. get the result and do (result XOR key) -> number
something better (stronger) would be to use any public-private key system. Exchange keys, crypt with public on one side, decrypt with private on the other side.
Related
I'm currently experimenting AES encryption using Google App Script, and I found out about cCryptoGS.
It feels weird, as like all ciphered texts seem to start with U2FsdGVkX1 (even though I change the part this is my passphrase in the example to something else very very different). I am not sure if I remembered correctly, I once tried AES in the past, but on Nodejs, and it looked just so much different, I'll get completely different text ciphered out even if I change only a single character in either my message, or my key.
Even in this post How is AES implemented in CryptoJS?, the ciphered text also starts with U2FsdGVkX1.
What I am asking is this: Is this cCryptoGS actually do what it claims to do? (i.e to apply AES encryption to a message)
Here's the website https://ramblings.mcpher.com/gassnippets2/cryptojs-libraries-for-google-apps-script/ There are also graphs on the site to show that Google App Script cannot handle complicated calculations well, so it looks legit, but the result seems to be so... weird... Since, overall AES seemed to be one of the best option to do encryption.
If this is indeed how AES should work, is there any way that I can make it seems more random? Thank you so much in advance, :(
Thank you very much in advance,
CryptoJS can process both passphrases and keys for encryption and decryption. Strings are interpreted as passphrases, WordArrays as keys, s. The Cipher Input.
cCryptoGS wraps the passphrase variant and supports the algorithms AES, DES, TripleDES and Rabbit, see Usage.
E.g. for AES, cCryptoGS/CryptoJS encrypts with AES-256, whereby a passphrase must be passed in addition to the plaintext.
Before encryption a random 8 bytes salt is generated and from passphrase and salt a 32 bytes key and 16 bytes IV is derived with the OpenSSL key derivation function EVP_BytesToKey().
The result is generated in OpenSSL format for compatibility with OpenSSL, which consists of the ASCII encoding of Salted__ followed by the 8 bytes salt and the actual ciphertext, with the entire expression Base64 encoded.
The Base64 encoding of Salted__ is U2FsdGVkX18=, where U2FsdGVkX1 is fixed (the last two characters depend on the 1st byte of the salt and can therefore change). Thus, any encryption starts with U2FsdGVkX1, but this does not reveal any information.
So yes, it is encrypted with AES-256, and the constant prefix U2FsdGVkX1 is not critical.
However, the key derivation function EVP_BytesToKey() is deemed insecure nowadays, especially with the parameters used by cCryptoGS/CryptoJS (broken MD5 digest and an iteration count of 1), s. e.g. here, 3rd part, so its use cannot actually be recommended (apart for compatibility maybe).
This applies to the wrapped functionalities that use passphrases for encryption/decryption. cCryptoGS also directly allows the use of CryptoJS functions, see CryptoJS direct, whose security is to be assessed individually.
The secure way is to pass key and IV directly, or when using a passphrase not to apply the built-in function EVP_BytesToKey(), but a reliable key derivation function like PBKDF2.
These variants are supported by CryptoJS, but apparently not by cCryptoGS, at least not by the wrapped functionalities.
Also note that at least the linked cCryptoGS sources seem to be based on CryptoJS version 3.1.2 which is from 2013, s. cCryptoGS sources (current CryptoJS version is 4.1.1).
Is there some library (preferably in javascript) that will classify a cookie value into some sensible data type?
When I look at various cookie values, I see various types such as:
plain english
numbers (hex, dec)
base64
some combination of above
It would be even more awesome if in addition to guessing the data-type, the library can also guess the type of encryption, or hashing used.
I remember experimenting with a python library a while ago but that did not seem to guess even simple hashes such as shasum, sha256sum, sha256sum, md5sum etc
There's no way to do this since all cookies are stored as string values. A workaround can be to classify them into general classes by putting them through regular expressions.
/^[0-9A-Fa-f]{8}$/ Signifying that could be an Adler-32 or CRC-32 Checksum
/^[0-9A-Fa-f]{32}$/ Signifying that could be an MD2, MD4, MD5, or Haval Sum
/^[0-9A-Fa-f]{64}$/ Signifying that could be a SHA-256 Sum
/^[0-9A-Fa-f]{96}$/ Signifying that could be a SHA-384 Sum
/^[0-9A-Fa-f]{128}$/ Signifying that could be a SHA-512 Sum
/^[^0-9A-Za-z+/]+={0,2}$/ Signifying that could be a Base-64 Encode
There's a chance that any one of these could just be regular numbers or plain test too (like "DEADBEEF"). If you're in charge of that data, I would specify the type in another cookie.
In summary, there's just no guarantee, unless you know what to expect.
I would like to get Both CryptoJS's SHA256 and php's Crypt SHA256 output to match.
PHP crypt has a salt and a number of rounds. E.g. for 5000 rounds and salt of "usesomesillystringforsalt" it would be;
$hash = crypt('Clear Text String', '$5$rounds=5000$usesomesillystringforsalt$');
I hope im not blind, but i cant find how to reproduce this behaviour in crypto-js. Its syntax doesn't seem to allow for rounds or salt.
Is it possible or should i just resort to using the basic PHP hash instead of crypt?
The CryptoJS API doesn't provide a way to specify a salt or the number of rounds for SHA256. You could add a salt manually if necessary, and specifying rounds doesn't make sense since "plain" SHA256 always uses a fixed number of rounds (64).
The number of rounds in PHP's crypt() actually defines how often the SHA256 algorithm is applied consecutively, in order to increase the complexity of brute force attacks. The PHP source code comments on this as follows: "Repeatedly run the collected hash value through SHA256 to burn CPU cycles".
As you can see in the source code (here and here), crypt() is actually a key derivation function that only makes use of SHA256 to generate cryptographically secure, salted hashes. So it also doesn't simply append the given salt to the key, instead it's a more elaborate process.
Therefore, it is not possible to get the same results with the algorithms provided by CryptoJS.
crypt() is mainly intended for password hashing. So if you need the hashes for another purpose, hash() is a good alternative (and of course creates exactly the same results as CryptoJS.SHA256()).
However, bear in mind that any cryptography with JavaScript is generally considered harmful. Hence, you should better use SSL in your application, if possible, and generate the hashes server side. If this is an option, have a look at bcrypt.
I want to generate a secure and ASCII encoded random nonce for my JavaScript program (it has to work in WebKit). Preferably, I want to use an off-the-shelf tool. So far, the only answers I found was this:
Secure random numbers in javascript?
The only problem with this is that the result is random, and I'm not sure how I can ASCII encode it without sacrificing security (i.e., making it less random).
Edit: Math.random() is not cryptographically secure, and window.crypto only generates values in multiples of a byte (ASCII values are 7 bits, so if the encoding mechanism is implemented naively, it would reduce the randomness).
You can encode arbitrary byte arrays as Base64 to get pure ASCII.
I am currently working on a project that will involve credit card swipes for admissions based on database rows. Like a will call system, the SHA-256 hash of the CC number must match the hash in the DB row in order to be considered the "proper pickup".
However, because the box office system is based in the browser, the CC number on pickup must be hashed client-side, using Javascript, and then compared to the previously downloaded will call data.
However when trying to hash the numbers, the hash always ends up different than what was hashed when the DB row was created (using VB.NET and SQL Server 2008 R2). For example, if a CC number in the database happened to be 4444333322221111, then the resulting hash from .NET would become xU6sVelMEme0N8aEcCKlNl5cG25kl8Mo5pzTowExenM=.
However, when using any SHA-256 hash library for Javascript I could find, the resulting hash would always be NbjuSagE7lHVQzKSZG096bHtQoMLscYAXyuCXX0Wtw0=.
I'm assuming this is some kind of Unicode/UTF-8 issue, but no matter what I try I cannot get the hashes to come out the same and it's starting to drive me crazy. Can anyone offer any advice?
Here's something that may provide some insight. Please go to http://www.insidepro.com/hashes.php?lang=eng and insert "4444333322221111" without quotes into the Password box. Afterwards, scroll down to the SHA-256 section.
You can see that there are four results, two of them are the hash codes I posted (the second from the top being the Javascript hash and the bottom one being the SQL hash). According to that page, the bottom hash result is generated using a base 64 string, as well as making the password into unicode format.
I've investigated this and tried many different functions to encode the password into unicode format, but no matter what little tweaks I try or other functions I make, I could never get it to match the hash code I need.
I am currently investigating the parameters used when calling the SHA-256 function on the server side.
UPDATE:
So just to make sure I wasn't crazy, I ran the Hash method I'm using for the CC numbers in the immediate window while debugging. Again, the result remains the same as before. You can see a screenshot here: http://i.imgur.com/raEyX.png
According to online SHA-256 hash calculator and a base-64 to hex decoder, it is the .NET implementation that has not calculated the hash correctly. You may want to double check the parameters you pass to the hashing functions.
When you are dealing with two untrusted implementations, it is always a good idea to find another independent implementation, and choose the one that matches the third one as correct. Either that, or find some test vectors, and validate the implementations individually.
EDIT:
A quick experiment shows that the SHA-256 hash you get from .NET matches the hext string 3400340034003400330033003300330032003200320032003100310031003100 - little endian 16-bit characters. Make sure you pass in ASCII.
Adam Liss had it right when he mentioned the byte arrays between strings in .NET/SQL Server are different than strings in Javascript. The array in .NET for the string 4444333322221111 would look like [52 0 52 0 52 0 52 0 51 0 51 0... etc.] and the same thing in Javascript would just look like [52 52 52 52 51 51 51 51...]. Thus, with different byte arrays, different hashes were generated.
I was able to remedy this for my application by modifying the base 64 SHA-256 hashing algorithm from here, where each character is pulled from the string one at a time in order to generate the hash.
Rather than having it do it this way, I first converted the string into a unicode-like byte array (like the .NET example above, 52 0 52 0 etc), fed that array to the hashing algorithm instead of the string, and did some very minor tweaks in order for it to grab each array member to generate the hash. Low and behold, it worked and now I have a very convenient method of hashing CC numbers in the same fashion as the .NET framework for quick and easy order lookup.
Are you sure about your JavaScript SHA256 function ?
And your firstly generated hash ?
SHA-256("4444333322221111"); // 35b8ee49a804ee51d5433292646d3de9b1ed42830bb1c6005f2b825d7d16b70d
hex: 35b8ee49a804ee51d5433292646d3de9b1ed42830bb1c6005f2b825d7d16b70d
HEX: 35B8EE49A804EE51D5433292646D3DE9B1ED42830BB1C6005F2B825D7D16B70D
h:e:x: 35:b8:ee:49:a8:04:ee:51:d5:43:32:92:64:6d:3d:e9:b1:ed:42:83:0b:b1:c6:00:5f:2b:82:5d:7d:16:b7:0d
base64: NbjuSagE7lHVQzKSZG096bHtQoMLscYAXyuCXX0Wtw0=