Why does AES decryption have one less round than AES encryption? - javascript

I'm doing some work on AES and I have been seeing lots of pseudocode where, for example, if encryption is done in 10 rounds, decryption is done in 9. Primarily this one, to be exact:
http://people.eku.edu/styere/Encrypt/JS-AES.html
Is this normal? Is there something I'm missing? Is it actually 10 rounds of decryption but I'm reading the code wrong?

The real question is why people trust these sites publishing some crappy JavaScript version of a cipher.
This is the official NIST pseudo code from FIPS 197:
Cipher(byte in[4*Nb], byte out[4*Nb], word w[Nb*(Nr+1)])
begin
byte state[4,Nb]
state = in
AddRoundKey(state, w[0, Nb-1])
for round = 1 step 1 to Nr–1
SubBytes(state)
ShiftRows(state)
MixColumns(state)
AddRoundKey(state, w[round*Nb, (round+1)*Nb-1]) end for
SubBytes(state)
ShiftRows(state)
AddRoundKey(state, w[Nr*Nb, (Nr+1)*Nb-1])
out = state
end
InvCipher(byte in[4*Nb], byte out[4*Nb], word w[Nb*(Nr+1)])
begin
byte state[4,Nb]
state = in
AddRoundKey(state, w[Nr*Nb, (Nr+1)*Nb-1])
for round = Nr-1 step -1 downto 1
InvShiftRows(state)
InvSubBytes(state)
AddRoundKey(state, w[round*Nb, (round+1)*Nb-1])
InvMixColumns(state) end for
InvShiftRows(state)
InvSubBytes(state)
AddRoundKey(state, w[0, Nb-1])
out = state
end
And bang, gone is the difference. The site you pointed to made a mistake, taking it up to 11 in the encryption routine.
When looking for code, test vectors use the original or original documents and specifications.

Related

Can one encrypt an n-digit number, returning a unique n-digit number?

StackOverflow warns me that I may be down-voted for this question, but I'd appreciate your not doing so, as I post this simply to try to understand a programming exercise I've been posed with, and over which I've been puzzling a while now.
I'm doing some javascript coding exercises and one of the assignments was to devise an "encryption function", encipher, which would encrypt a 4-digit number by multiplying it by a number sufficiently low such that none of its digits exceeds 9, so that a 4-digit number is returned. Thus
encipher(0204)
might yield
0408
where the multiplier would have been 2. -- This is very basic material, simply to practice the Javascript. -- But as far as I can see, the numbers returned can never be deciphered (which is the next part of the exercise). Even if you store a dictionary internal to encipher, along the lines of
{'0408':'2'}, etc
so that you could do a lookup on 0408 and return 0204, these entries could not be assured to be unique. If one for example were to get the number 9999 to be deciphered, one would never know whether the original number was 9999 (multiplied by 1), 3333 (multiplied by 3) or 1111 (multiplied by 9). Is that correct? I realise this is a fairly silly and artificial problem, but I'm trying to understand if the instructions to the exercise are not quite right, or if I'm missing something. Here is the original problem:
Now, let's add one more level of security. After changing the position of the digits, we will multiply each member by a number whose multiplication does not exceed 10. (If it is higher than 10, we will get a two-digit multiplication and the code will no longer be 4 values). Now, implement in another function the decrypter (), which will receive as an argument an encrypted code (and correspondingly multiplied in the section above and return the decrypted code.
Leaving the exercise behind, I'm just curious whether there exists any way to "encrypt" (when I say "encrypt", I mean at a moderate javascript level, as I'm not a cryptography expert) an n-digit number and return a unique n-digit number?
Thanks for any insights. --
encrypt a 4-digit number by multiplying it by a number sufficiently low such that none of its digits exceeds 9, so that a 4-digit number is returned
If your input is 9999, there is no integer other than 1 or 0 that you can multiply your input by and get a positive number with a maximum of 4 digits. Therefore, there is no solution that involves only integer multiplication. However, integer multiplication can be used as part of an algorithm such as rotating digits (see below).
If instead you're looking for some sort of bijective algorithm (one that uniquely maps A to B and B to A), you can look at something like rotating the digits left or right, reversing the order of the digits, or using a unique mapping of each individual digit to another. Those can also be mixed.
Examples
Rotate
1234 -> 2341
Reverse
1234 -> 4321
Remap digits e.g. 2 mapped to 8, 3 mapped to 1
2323 -> 8181
Note that none of these are cryptographically sound methods to encrypt information, but they do seem to more-or-less meet the objectives of the exercise.

Reassembling negative Python marshal int's into Javascript numbers

I'm writing a client-side Python bytecode interpreter in Javascript (specifically Typescript) for a class project. Parsing the bytecode was going fine until I tried out a negative number.
In Python, marshal.dumps(2) gives 'i\x02\x00\x00\x00' and marshal.dumps(-2) gives 'i\xfe\xff\xff\xff'. This makes sense as Python represents integers using two's complement with at least 32 bits of precision.
In my Typescript code, I use the equivalent of Node.js's Buffer class (via a library called BrowserFS, instead of ArrayBuffers and etc.) to read the data. When I see the character 'i' (i.e. buffer.readUInt8(offset) == 105, signalling that the next thing is an int), I then call readInt32LE on the next offset to read a little-endian signed long (4 bytes). This works fine for positive numbers but not for negative numbers: for 1 I get '1', but for '-1' I get something like '-272777233'.
I guess that Javascript represents numbers in 64-bit (floating point?). So, it seems like the following should work:
var longval = buffer.readInt32LE(offset); // reads a 4-byte long, gives -272777233
var low32Bits = longval & 0xffff0000; //take the little endian 'most significant' 32 bits
var newval = ~low32Bits + 1; //invert the bits and add 1 to negate the original value
//but now newval = 272826368 instead of -2
I've tried a lot of different things and I've been stuck on this for days. I can't figure out how to recover the original value of the Python integer from the binary marshal string using Javascript/Typescript. Also I think I deeply misunderstand how bits work. Any thoughts would be appreciated here.
Some more specific questions might be:
Why would buffer.readInt32LE work for positive ints but not negative?
Am I using the correct method to get the 'most significant' or 'lowest' 32 bits (i.e. does & 0xffff0000 work how I think it does?)
Separate but related: in an actual 'long' number (i.e. longer than '-2'), I think there is a sign bit and a magnitude, and I think this information is stored in the 'highest' 2 bits of the number (i.e. at number & 0x000000ff?) -- is this the correct way of thinking about this?
The sequence ef bf bd is the UTF-8 sequence for the "Unicode replacement character", which Unicode encoders use to represent invalid encodings.
It sounds like whatever method you're using to download the data is getting accidentally run through a UTF-8 decoder and corrupting the raw datastream. Be sure you're using blob instead of text, or whatever the equivalent is for the way you're downloading the bytecode.
This got messed up only for negative values because positive values are within the normal mapping space of UTF-8 and thus get translated 1:1 from the original byte stream.

True or better Random numbers with Javascript [duplicate]

This question already has answers here:
Secure random numbers in javascript?
(10 answers)
Closed 12 months ago.
I have all kinds of resources that rely on javascript random numbers. However, I've been seeing a lot of problems where random isn't so random because of the way I'm generating random numbers.
Is there any javascript resource for me to generate true, or just better random numbers?
I know that I can interface with Random.org, but what other options do I have?
I'm using:
function rand( lowest, highest){
var adjustedHigh = (highest - lowest) + 1;
return Math.floor(Math.random()*adjustedHigh) + parseFloat(lowest);
}
Assuming you're not just seeing patterns where there aren't any, try a Mersenee Twister (Wikipedia article here). There are various implementations like this one on github.
Similar SO question:
Seedable JavaScript random number generator
If you want something closer to truly random, then consider using the random.org API to get truly random numbers, although I would suggest only using that to seed, not for every number, as you need to abide by their usage limits.
Tweaking numbers so they "look random"
I agree with Phil H that humans are so good at finding patterns that they often think they see patterns even in "perfectly random" sequences of numbers (clustering illusion, apophenia, gambler's fallacy, etc).
Plots of true random positions generally have lots of clumps and points that "coincidentally" fall very close together, which looks pretty suspicious.
Artists often take completely randomly generated patterns and "nudge" them to make them appear "more random", even though that careful nudging actually makes the pattern less random (a), (b), (c), (d), etc.
Alternatively, a low-discrepancy sequence sometimes "looks better" than a true random sequence and is much faster to generate.
Fast random number generators
There are many "random number generators" across a whole spectrum from "extremely fast" to "relatively slow" and from "easy for even a human to see patterns" to "unlikely that unassisted humans could ever see any patterns" to "cryptographically secure and, after seeded with adequate amounts of entropy, as far as we can tell, indistinguishable from random to any attacker using less than all the energy produced by humanity for a month."
Non-cryptographic-strength random number generators that still give excellent output (unlikely that unassisted humans could ever see any patterns) include the Mersenne twister, multiply-with-carry, Lagged Fibonacci generator, Well equidistributed long-period linear, Xorshift, etc.
Cryptographic random number techniques that work with some browsers
I hear that Cryptocat and other JavaScript applications use the convenient window.crypto.getRandomValues() or window.msCrypto.getRandomValues() or SubtleCrypto.generateKey() functions that are designed to generate cryptographic random numbers. Unfortunately, that function is not available in IE 11 and below.
Since web browsers use random numbers all the time (for every "https://" page they fetch), it's quite likely that these functions (where available) may run faster than most random number generators written in JavaScript -- even non-cryptographic algorithms.
Cryptographic random number techniques compatible with ancient and modern browsers
One way to generate true random numbers in JavaScript is to capture mouse events and add them into a pool of entropy, keeping track of some (hopefully conservative) estimate of the entropy added. Once the pool is "full" (estimates indicate that at least 128 bits of entropy have been added), use some cryptographically secure random number generator to generate random numbers from the pool -- typically by using a one-way hash so that a sequence of a few thousand output numbers are not enough to deduce the state of the entropy pool and hence predict the next output number.
One implementation: http://lightsecond.com/passphrase.html
Further reading
window.crypto
Compatibility of window.crypto.getRandomValues()
Secure random numbers in javascript?
https://security.stackexchange.com/questions/20029/generate-cryptographically-strong-pseudorandom-numbers-in-javascript
Is there any built in browser support for crypto random numbers in IE and Webkit? Firefox has window.crypto
Better random function in JavaScript
While looking for an alternative for Math.random I stumbled on this question.
While those are valid answers, the solution that worked for me was simply using Math.random twice.
And use a modulus on the decimals of the float.
Basically to increase the randomness.
Maybe it might be usefull for some who were guided by google to this question.
Here's a snippet with the function, and one that runs it a million times.
function rand(min, max){
return (Math.floor(Math.pow(10,14)*Math.random()*Math.random())%(max-min+1))+min;
}
// testing rand
function rollRands(min, max, rolls) {
let roll = 0, n = 0;
let counts = {};
for(let i = min; i <= max; i++){
counts[i]=0
}
while (roll < rolls){
roll++;
counts[rand(min,max)]++;
}
return counts;
}
console.log(rollRands(36, 42, 1000000));
Rando.js is cryptographically secure. It's basically window.crypto.getRandomValues() that uses window.msCrypto.getRandomValues() as a failsafe and Math.random() as a last resort failsafe, but it's easier to implement and use. Here's a basic cryptographically secure random [0, 1) number:
console.log(rando());
<script src="https://randojs.com/2.0.0.js"></script>
Nice and easy. If that's all you wanted, you're good to go. If you want it to do more for you, it's also capable of all this:
console.log(rando(5)); //an integer between 0 and 5 (could be 0 or 5));
console.log(rando(5, 10)); //a random integer between 5 and 10 (could be 5 or 10));
console.log(rando(5, "float")); //a floating-point number between 0 and 5 (could be exactly 0, but never exactly 5));
console.log(rando(5, 10, "float")); //a floating-point number between 5 and 10 (could be exactly 5, but never exactly 10));
console.log(rando(true, false)); //either true or false
console.log(rando(["a", "b"])); //{index:..., value:...} object representing a value of the provided array OR false if array is empty
console.log(rando({a: 1, b: 2})); //{key:..., value:...} object representing a property of the provided object OR false if object has no properties
console.log(rando("Gee willikers!")); //a character from the provided string OR false if the string is empty. Reoccurring characters will naturally form a more likely return value
console.log(rando(null)); //ANY invalid arguments return false
//Prevent repetitions by grabbing a sequence and looping through it
console.log(randoSequence(5)); //an array of integers from 0 through 5 in random order
console.log(randoSequence(5, 10)); //an array of integers from 5 through 10 in random order
console.log(randoSequence(["a", "b"])); //an array of {index:..., value:...} objects representing the values of the provided array in random order
console.log(randoSequence({a: 1, b: 2})); //an array of {key:..., value:...} objects representing the properties of the provided object in random order
console.log(randoSequence("Good gravy!")); //an array of the characters of the provided string in random order
console.log(randoSequence(null)); //ANY invalid arguments return false
<script src="https://randojs.com/2.0.0.js"></script>
It supports working with jQuery elements too, but I left that out of this demo so I wouldn't have to source in jQuery. If you need that, just check it out on the GitHub or website.
There seems to be slight confusion here between two things that are very different:
random numbers;
pseudorandom numbers.
Apologies to those who know this already, but the two are worlds apart. Pseudorandom numbers appear random and may even pass sophisticated tests of randomness, but they are deterministic. Because of this, they are useless for cryptography, and may have other flaws where true randomness is required.
True randomness is non-deterministic, and thus unpredictable. A key concept here is one of entropy, or the amount of non-redundant information contained. There is a limited number of ways of obtaining truly random data. 'Good' sources are:
Radioactive decay — often difficult to do;
Background radio noise — contrary to popular believe, this is mostly not related to the background microwave radiation from the big bang, but more parochial;
The noise from electrons moving across a reverse-biased Zener diode: actually quite useful and easy to implement in practice, with simple circuitry.
Other 'sources of randomness' like mouse movements and internal variations in computer disk timing, etc. are often harnessed, but may be less-than-perfect. Generally, I've found that it's easier to access the entropy pool on a Linux system than under Windows, but this may just be personal bias.
If you just want random-appearing numbers, then yes, using the Mersenne twister is a viable option. It jumps around like crazy. If you're generating random numbers to use as e.g. version 4 UUIDs, then you need to be more careful. You can't simply 'add entropy' if it's not there, even by applying deterministic cryptographic functions.
If you intend to use your randomness for cryptography, you should also be intensely aware of the many ways your source of randomness can become compromised. For example, if you're using an Internet-based 'source of randomness', who can tap into this?
Even better, you can use quantum cryptography to generate randomness that is very hard to predict. You can use the ANU Quantum Random Numbers API for some randomness that is coercible into a number similarly output by Math.random.
you can generate a pool of random numbers just by requesting some data asynchronously because performance.now() gives you time precision up to microseconds. Then use the response time as a salt in a randomising algorithm,
var randomNumbers = [];
for(var i = 0; i < 10; i++) {
setTimeout(function () {
var timeStart = performance.now();
xhttp = new XMLHttpRequest();
xhttp.open('GET', 'https://cdn.polyfill.io/v2/polyfill.min.js?rand=' + Math.random(), true);
xhttp.onload = function () {
var timeEnd = performance.now() - timeStart;
var rNumber = parseInt(timeEnd.toString().replace('.', ''));
randomNumbers.push(rNumber)
};
xhttp.send();
}, i * 10);
}
There are many factors that will affect this time:
browser speed
route one way
server response time
route back
It's not good to generate millions of numbers this way but a few. Maybe concatenate a few results to get a good, long random number.

Include nonce and block count in PyCrypto AES MODE_CTR

Some background information, you can skip this part for the actual question
this is my third question about this topic here at stackoverflow. To be complete, these are the other questions AES with crypt-js and PyCrypto and Match AES de/encryption in python and javascript. Unfortunately my last attempt got two downvots for the original question. The problem was, even I did not know what my real question was. I just dug around to find the real question I was looking for. With the feedback in the comments, and reading some additional information, I updated my question. I excavate the right question, I think. But my problem didn't get any more views after my updates. So I really hope, that this question is now more clear and understandable - even I know what my Problem is now :D
Thank you all for making stackoverflow to this cool community - I often found here solutions for my problems. Please keep giving feedback to bad questions, so they can be improved and updated, which increases this huge knowledge and solutions database.
And feel free to correct my english grammar and spelling.
The Problem
AES in Javascript
I have an encrypted String which I can decrypt with this this Javascript Implementation of AES 256 CTR Mode
password = "myPassphrase"
ciphertext = "bQJdJ1F2Y0+uILADqEv+/SCDV1jAb7jwUBWk"
origtext = Aes.Ctr.decrypt(ciphertext, password, 256);
alert(origtext)
This decrypts my string and the alert box with This is a test Text pops up.
AES with PyCrypto
Now I want to decrypt this string with python and PyCrypto
password = 'myPassphrase'
ciphertext = "bQJdJ1F2Y0+uILADqEv+/SCDV1jAb7jwUBWk"
ctr = Counter.new(nbits=128)
encryptor = AES.new(key, AES.MODE_CTR, counter=ctr)
origtext = encryptor.decrypt(base64.b64decode(ciphertext))
print origtext
This code does not run. I get an ValueError: AES key must be either 16, 24, or 32 bytes long. When I recognized, that I have to do more in PyCrypto then just call a decrypt method, I started to investigate end try to figure out what I have to do.
Investigation
The basic things I figured out first, were:
AES 256 Bit (?). But AES standard is 128 bit. Does increasing the passphrase to 32 Byte is enough?
Counter Mode. Easily to set in PyCrypto with AES.MODE_CTR. But I have to specify a counter() Method. So I used the basic binary Counter provided by PyCrypto. Is this compatible with the Javascript Implementation? I can't figure out what they are doing.
The string is base64 encoded. Not a big problem.
Padding in general. Both passphrase and the encrypted string.
For the passphrase they do this:
for (var i=0; i<nBytes; i++) {
pwBytes[i] = isNaN(password.charCodeAt(i)) ? 0 : password.charCodeAt(i);
}
Then I did this in python
l = 32
key = key + (chr(0)*(l-len(key)%l))
But this did not help. I still get a weird string ?
A???B??d9= ,?h????' with the following code
l = 32
key = 'myPassphrase'
key = key + (chr(0)*(l-len(key)%l))
ciphertext = "bQJdJ1F2Y0+uILADqEv+/SCDV1jAb7jwUBWk"
ctr = Counter.new(nbits=128)
encryptor = AES.new(key, AES.MODE_CTR, counter=ctr)
origtext = encryptor.decrypt(base64.b64decode(ciphertext))
print origtext
Then I read more about the Javascript Implementation and it says
[...] In this implementation, the initial block holds the nonce in the first 8 bytes, and the block count in the second 8 bytes. [...]
I think this could be the key to the solution. So I tested what happens when I encrypt an empty string in Javascript:
origtext = ""
var ciphertext =Aes.Ctr.encrypt(origtext, password, 256);
alert(ciphertext)
The alert box shows /gEKb+N3Y08= (12 characters). But why 12? Shouldn't it be 8+8 = 16Bytes? Well anyway, I tried a bruteforce method on the python decryption by testing the decryption with for i in xrange(0,20): and ciphertext[i:] or base64.b64decode(ciphertext)[i:]. I know this is a very embarrassing try, but I got more and more desperate. And it didn't work either.
The future prospects are also to implement the encryption in the same way.
additional information
The encrypted string was not originally encrypted with this Javascript implementation, It's from another source. I just recognized, that the Javascript code does the right thing. So I affirm that this kind of implementation is something like a "standard".
The question
What can I do, that the encryption and decryption from a string with PyCrypto is the same like in the Javascript implementation, so that I can exchange data between Javascript and Python?
I also would switch to another crypto library in python, if you can suggest another one.
Furthermore I'm happy with any kind of tips and feedback.
And I think, all comes down to How can I include the nonce and block count to the encrypted string? and How can I extract this information for decryption?
We are still dealing with a bunch of questions here.
How can I extract the nonce and the counter for decryption?
This is easy. In the Javascript implementation (which does not follow a particular
standard in this respect) the 8-byte nonce is prepended to the encrypted result.
In Python, you extract it with:
import base64
from_js_bin = base64.decode(from_js)
nonce = from_js_bin[:8]
ciphertext = from_js_bin[8:]
Where from_js is a binary string you received.
The counter cannot be extracted because the JS implementation does not transmit it.
However, the initial value is (as typically happens) 0.
How can I use the nonce and counter to decrypt the string in Python?
First, it must be established how nonce and counter are combined to get the counter block.
It seems that the JS implementation follows the NIST 800-38A standard, where the
left half is the nonce, and the right half is the counter. More precisely, the counter
is in big endian format (LSB is the rightmost byte). This is also what Wikipedia shows:
.
Unfortunately, CTR mode is poorly documented in PyCrypto (a well-known problem).
Basically, the counter parameter must be a callable object that returns
the correct 16-byte (for AES) counter block, for each subsequent call.
Crypto.Util.Counter does that, but in an obscure way.
It is there only for performance purposes though. You can easily implement it yourself like this:
from Crypto.Cipher import AES
import struct
class MyCounter:
def __init__(self, nonce):
"""Initialize the counter object.
#nonce An 8 byte binary string.
"""
assert(len(nonce)==8)
self.nonce = nonce
self.cnt = 0
def __call__(self):
"""Return the next 16 byte counter, as binary string."""
righthalf = struct.pack('>Q',self.cnt)
self.cnt += 1
return self.nonce + righthalf
cipher_ctr = AES.new(key, mode=AES.MODE_CTR, counter=MyCounter(nonce))
plaintext = cipher_ctr.decrypt(ciphertext)
How long is the key for AES?
The key length for AES-128 is 16 bytes.
The key length for AES-192 is 24 bytes.
The key length for AES-256 is 32 bytes.
Each algorithm is different, but much of the implementation is shared.
In all cases, the algorithm operate on 16 byte blocks of data.
For simplicity, stick to AES-128 (nBits=128).
Will your code work?
I have the feeling it won't, because the way you compute the AES key seems incorrect.
The JS code encodes the password in UTF-8 and encrypts it with itself.
The result is the actual key material. It is 16 byte long, so for AES-192 and -256, the implementation copies part of it at the back. Additionally, the plaintext is also UTF-8 encoded before encryption.
In general, I suggest you follow this approach:
Make your JS implementation reproducible (right now encryption depends on the current time, which changes quite often ;-) ).
Print the value of the keys and data at each step (or use a debugger).
Try to reproduce the same algorithm in Python, and print the values too.
Investigate where they start to differ.
Once you have duplicated the encryption algorithm in Python, the decryption one should be easy.

SSH documentation confusion

I'm trying to create a very simple & lightweight client implementation of the SSH protocol for node.js.
The following documentation confuses me totally:
http://www.snailbook.com/docs/transport.txt
It lacks a full example of the whole key exchange thing. There are many things well explained, but I'm not really sure how to put those things together.
Could you help me to put an example together?
I'm stuck after section 7.1. I successfully receive the list of alorightms of the server, and I send a list with only the required alorithms to the server. Also successful.
So, in this case we have the following alorightms:
kex: diffie-hellman-group1-sha1
key: ssh-dss
encryption: 3des-cbc
mac: hmac-sha1
After that, I skipped section 7.2 and 7.3 and continued directly to section 8, since generating a key needs the values H & K, which are generated in section 8.
But section 8 does not make sense to me. It requires both the client & the server to already know the same prime, generator and order value. When have those values been negotiated an sent to each other? Section 8 cleary says that it directly follows the algorithm exchange, so there is nothing between those steps...
Am I missing something?
Thanks really much for your help!
The prime is specified by the key-exchange algorithm. For example, to quote from your source:
The "diffie-hellman-group1-sha1" method specifies the Diffie-Hellman key exchange with SHA-1 as HASH, and Oakley Group 2 [RFC2409] (1024-bit MODP Group).
And if you consult RFC 2409 §6.2, you'll find:
The prime is 2^1024 - 2^960 - 1 + 2^64 * { [2^894 pi] + 129093 }. Its hexadecimal value is FFFFFFFF FFFFFFFF C90FDAA2 2168C234 C4C6628B 80DC1CD1
29024E08 8A67CC74 020BBEA6 3B139B22 514A0879 8E3404DD
EF9519B3 CD3A431B 302B0A6D F25F1437 4FE1356D 6D51C245
E485B576 625E7EC6 F44C42E9 A637ED6B 0BFF5CB6 F406B7ED
EE386BFB 5A899FA5 AE9F2411 7C4B1FE6 49286651 ECE65381
FFFFFFFF FFFFFFFF The generator is 2 (decimal)

Categories

Resources