Related: How do I test my encryption? (absolute amateur)
I was making a secret santa with friends and got carried away by allowing everyone to include a password. I'm doing this in Excel and decided to try an encryption idea with matrices. The method I've come up with involves hashing the password, encrypting the name of the user's target with that hash as a key, then they can type the password in to unencrypt it.
I'm using a salt (per user) to avoid hash collisions for same password or rainbow table attacks although come to think of it there won't be any precalculated hashes for my weird hashing function so maybe I can drop that.
To make all this work I'm leveraging a property of matrices that if you multiply a matrix by another "singular" matrix, you cannot undo that operation.
Hashing Function
So let's say I have the users password as matrix $P$ the hashed result $H = P*M$ where $*$ denotes Matrix multiplication and $M$ is another matrix that does the hashing. Now the keen observer will notice I can undo matrix multiplication to recover the password from the Hash: $H*M^{-1}=P*M*M^{-1}=P$.
The solution is to ensure $M$ is singular and so multiplying by it cannot be reversed, as it has no inverse. A simple way to do this is to use a triangular matrix with a single 0 on its diagonal, since the determinant of a triangular matrix is the product of its diagonal.
Now to add some randomness, I add salt which is another matrix of random data, giving
$H = (P \cdot S) * M$ where the $\cdot$ could be any operation, even $H = P*S*M$
The hash is saved alongside the salt and the username in my database
Encrypting
To encrypt/ decrypt data using the password hash, I used matrices again. This time, if I have data $D$ then encrypted date $E = D * (H + K)$ where K is a constant offset to make sure $H + K$ is not singular. Then to get my data back I just use $D = E * (H+K)^{-1}$, which of course only works if the user provides the right hash.
In fact once I have the Encrypted value, I can save
Username | Encrypted | Salt
in my database, since the Hash is generated by typing the password anyway.
Worked example
$$ (P)assword = \begin{pmatrix} 72 & 69 & 76 & 76\\ 79 & 1 & 87 & 79\\ 82 & 76 & 68 & 33\\ 1 & 1 & 1 & 1 \end{pmatrix} $$
$$ (S)alt = \begin{pmatrix} 0.9806 & 0.3761 & 0.4784 & 0.3156\\ 0.6299 & 0.0492 & 0.8771 & 0.9884\\ 0.9024 & 0.3252 & 0.2534 & 0.7564\\ 0.7803 & 0.2599 & 0.6933 & 0.303 \end{pmatrix} $$
$$ Singular Hashing (M)atrix = \begin{pmatrix} 1 & 0 & 0 & 0\\ 1 & 1 & 0 & 0\\ 1 & 1 & 0 & 0\\ 1 & 1 & 1 & 1 \end{pmatrix} $$
$$ (H)ash = P * S * M = \begin{pmatrix} 655.2442 & 413.2927 & 171.4372 & 171.4372\\ 527.9872 & 309.7374 & 115.6646 & 115.6646\\ 589.0947 & 373.7 & 162.4318 & 162.4318\\ 8.9692 & 5.676 & 2.3634 & 2.3634 \end{pmatrix} $$
And then to encrypt data $E$, simply multiply it by $H + K$ where $K$ is any non-singular matrix. This could maybe be the pepper I think if I understand that term correctly, a constant secret value for all that can be swapped from time to time to re-encrypt everything.
Practical considerations (not for review)
- I think computers are fast at matrix operations, so I suppose a nice thing about this encryption process is no special dedicated hardware needed, and quite quick to do key extension (repeatedly hash is just repeated matrix multiplication)
- For the password and data, I need square matrices so I encode the strings as length prefixed arrays of character codes with repeating the array to fill any space (e.g. 4 x 4 matrix needs 16 chars, so 10 char password becomes
10 my pa ss wo rd my pa ssor something like that. - There is probably a way to encode the data so it makes similar data generate more distinct hashes (nearby hashes don't appear nearby) although I don't know how to analyse if this will be a problem - since matrix multiplication looks at many elements at the same time, it feels like changing one character in the password will change many elements in the hash.
- For illustration I've used floating point numbers which could give rounding errors - for the hash that means more hash collisions, for the decryption that's possible data loss. I suppose technically we could specify the $P$, $S$ and $M$ matrices are 8 bit entries, therefore the $H$ is maybe 32 bit entries to account for multiplying the 3 above and adding their dimensions etc.
- Some thought is needed for long passwords exceeding the 4x4 matrix dimensions - maybe they could be broken into several matrices and multiplied with overflow, the hash will have more collisions but still won't be crackable (reversible). I haven't really thought much about this, I just put length limit on the thing being hashed.