рдШрд░ рдкрд░ рдЗрд╕реЗ рдХрднреА рди рджреЛрд╣рд░рд╛рдПрдВ: HC-128 рдПрдиреНрдХреНрд░рд┐рдкреНрд╢рди рдПрд▓реНрдЧреЛрд░рд┐рдердо рдХрд╛ рд╕рдВрд╢реЛрдзрди


HC-128 (рдкреАрдбреАрдПрдл) - рдпреВрд░реЛрдкреАрдп рдкрд░рд┐рдпреЛрдЬрдирд╛ рдХреЗ рдЕрдВрддрд┐рдо , eSTREAM , рдПрдХ рдХрд╛рдлреА рдмрдбрд╝реЗ рдЖрдВрддрд░рд┐рдХ рд░рд╛рдЬреНрдп рдХреЗ рд╕рд╛рде рдзрд╛рд░рд╛ рд╕рд┐рдлрд░
(512 32 рдмрд┐рдЯ рд╢рдмреНрджреЛрдВ рдХреЗ 2 рд╕реНрд╡рддрдВрддреНрд░ рд╕рд░рдгрд┐рдпрд╛рдБ)ред рдпрджрд┐ рдЖрдк рдмрдбрд╝реА рдзрд╛рд░рд╛рдУрдВ рдХреЛ рдПрдиреНрдХреНрд░рд┐рдкреНрдЯ рдХрд░рддреЗ рд╣реИрдВ, рддреЛ рдпрд╣ рдмрд╣реБрдд рд╕реНрдорд╛рд░реНрдЯ рд╣реИ, рд▓реЗрдХрд┐рди рдЪреВрдВрдХрд┐ рдЗрди рд╕рд░рдгрд┐рдпреЛрдВ рдХреЗ рдЖрд░рдВрдн рдореЗрдВ рдПрдХ рд╕рднреНрдп рд╕рдордп рд▓рдЧрддрд╛ рд╣реИ, рдЗрд╕рд▓рд┐рдП рдпрд╣ рдмреИрдЪ рдореЛрдб рдореЗрдВ рдмрд╣реБрдд рдХреБрд╢рд▓ рдирд╣реАрдВ рд╣реИред рджрд╛рдИрдВ рдУрд░ 6 рдореБрдЦреНрдп рдХрд╛рд░реНрдп рд╣реИрдВ рдЬреЛ рдЗрд╕рдореЗрдВ рдЙрдкрдпреЛрдЧ рдХрд┐рдП рдЬрд╛рддреЗ рд╣реИрдВред рдпрд╣ рд╕реНрдерд┐рд░рд╛рдВрдХ рдХреЗ рдбрд░рд╛рд╡рдиреЗ рд▓рдВрдмреЗ рд╕рд░рдгрд┐рдпреЛрдВ рдХреЗ рд╕рд╛рде рдЕрддрд┐рднрд╛рд░рд┐рдд рдирд╣реАрдВ рд╣реИ, рдЗрд╕рдХрд╛ рдХрд╛рд░реНрдпрд╛рдиреНрд╡рдпрди (рдХрдЯреМрддреА рдХреЗ рддрд╣рдд), рджреВрд╕рд░реЛрдВ рдХреА рддреБрд▓рдирд╛ рдореЗрдВ, рд╕рд░рд▓ рдФрд░ рдХрдо рдпрд╛ рдЬреНрдпрд╛рджрд╛ рд╕реНрдкрд╖реНрдЯ рджрд┐рдЦрддрд╛ рд╣реИред рдпрд╣ рд╕рдм рдЗрд╕ рддрдереНрдп рд╕реЗ рд╢реБрд░реВ рд╣реБрдЖ рдХрд┐ рджреЛ рдХрд╛рд░реНрдп f1 рдФрд░ f2 рдиреЗ рдореБрдЭреЗ рдЭреБрдХрд╛ рджрд┐рдпрд╛


рдпрд╣рд╛рдБ BouncyCastle рд▓рд╛рдЗрдмреНрд░реЗрд░реА рд╕реЗ рд▓рд┐рдпрд╛ рдЧрдпрд╛ рдорд╛рдирдХ рдХрд╛рд░реНрдпрд╛рдиреНрд╡рдпрди рд╣реИ

рдХреЛрд░реНрдЯ-128
package org.bouncycastle.crypto.engines; import org.bouncycastle.crypto.CipherParameters; import org.bouncycastle.crypto.DataLengthException; import org.bouncycastle.crypto.StreamCipher; import org.bouncycastle.crypto.params.KeyParameter; import org.bouncycastle.crypto.params.ParametersWithIV; /** * HC-128 is a software-efficient stream cipher created by Hongjun Wu. It * generates keystream from a 128-bit secret key and a 128-bit initialization * vector. * <p> * http://www.ecrypt.eu.org/stream/p3ciphers/hc/hc128_p3.pdf * </p><p> * It is a third phase candidate in the eStream contest, and is patent-free. * No attacks are known as of today (April 2007). See * * http://www.ecrypt.eu.org/stream/hcp3.html * </p> */ public class HC128Engine implements StreamCipher { private int[] p = new int[512]; private int[] q = new int[512]; private int cnt = 0; private static int f1(int x) { return rotateRight(x, 7) ^ rotateRight(x, 18) ^ (x >>> 3); } private static int f2(int x) { return rotateRight(x, 17) ^ rotateRight(x, 19) ^ (x >>> 10); } private int g1(int x, int y, int z) { return (rotateRight(x, 10) ^ rotateRight(z, 23)) + rotateRight(y, 8); } private int g2(int x, int y, int z) { return (rotateLeft(x, 10) ^ rotateLeft(z, 23)) + rotateLeft(y, 8); } private static int rotateLeft( int x, int bits) { return (x << bits) | (x >>> -bits); } private static int rotateRight( int x, int bits) { return (x >>> bits) | (x << -bits); } private int h1(int x) { return q[x & 0xFF] + q[((x >> 16) & 0xFF) + 256]; } private int h2(int x) { return p[x & 0xFF] + p[((x >> 16) & 0xFF) + 256]; } private static int mod1024(int x) { return x & 0x3FF; } private static int mod512(int x) { return x & 0x1FF; } private static int dim(int x, int y) { return mod512(x - y); } private int step() { int j = mod512(cnt); int ret; if (cnt < 512) { p[j] += g1(p[dim(j, 3)], p[dim(j, 10)], p[dim(j, 511)]); ret = h1(p[dim(j, 12)]) ^ p[j]; } else { q[j] += g2(q[dim(j, 3)], q[dim(j, 10)], q[dim(j, 511)]); ret = h2(q[dim(j, 12)]) ^ q[j]; } cnt = mod1024(cnt + 1); return ret; } private byte[] key, iv; private boolean initialised; private void init() { if (key.length != 16) { throw new java.lang.IllegalArgumentException( "The key must be 128 bits long"); } cnt = 0; int[] w = new int[1280]; for (int i = 0; i < 16; i++) { w[i >> 2] |= (key[i] & 0xff) << (8 * (i & 0x3)); } System.arraycopy(w, 0, w, 4, 4); for (int i = 0; i < iv.length && i < 16; i++) { w[(i >> 2) + 8] |= (iv[i] & 0xff) << (8 * (i & 0x3)); } System.arraycopy(w, 8, w, 12, 4); for (int i = 16; i < 1280; i++) { w[i] = f2(w[i - 2]) + w[i - 7] + f1(w[i - 15]) + w[i - 16] + i; } System.arraycopy(w, 256, p, 0, 512); System.arraycopy(w, 768, q, 0, 512); for (int i = 0; i < 512; i++) { p[i] = step(); } for (int i = 0; i < 512; i++) { q[i] = step(); } cnt = 0; } public String getAlgorithmName() { return "HC-128"; } /** * Initialise a HC-128 cipher. * * @param forEncryption whether or not we are for encryption. Irrelevant, as * encryption and decryption are the same. * @param params the parameters required to set up the cipher. * @throws IllegalArgumentException if the params argument is * inappropriate (ie. the key is not 128 bit long). */ public void init(boolean forEncryption, CipherParameters params) throws IllegalArgumentException { CipherParameters keyParam = params; if (params instanceof ParametersWithIV) { iv = ((ParametersWithIV)params).getIV(); keyParam = ((ParametersWithIV)params).getParameters(); } else { iv = new byte[0]; } if (keyParam instanceof KeyParameter) { key = ((KeyParameter)keyParam).getKey(); init(); } else { throw new IllegalArgumentException( "Invalid parameter passed to HC128 init - " + params.getClass().getName()); } initialised = true; } private byte[] buf = new byte[4]; private int idx = 0; private byte getByte() { if (idx == 0) { int step = step(); buf[0] = (byte)(step & 0xFF); step >>= 8; buf[1] = (byte)(step & 0xFF); step >>= 8; buf[2] = (byte)(step & 0xFF); step >>= 8; buf[3] = (byte)(step & 0xFF); } byte ret = buf[idx]; idx = idx + 1 & 0x3; return ret; } public void processBytes(byte[] in, int inOff, int len, byte[] out, int outOff) throws DataLengthException { if (!initialised) { throw new IllegalStateException(getAlgorithmName() + " not initialised"); } if ((inOff + len) > in.length) { throw new DataLengthException("input buffer too short"); } if ((outOff + len) > out.length) { throw new DataLengthException("output buffer too short"); } for (int i = 0; i < len; i++) { out[outOff + i] = (byte)(in[inOff + i] ^ getByte()); } } public void reset() { idx = 0; init(); } public byte returnByte(byte in) { return (byte)(in ^ getByte()); } } 



рдХрд╛рд░реНрдпреЛрдВ рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ f1 рдФрд░ f2 рдЬреЛ рдореИрдВрдиреЗ рдкрд╣рд▓реЗ рд▓рд┐рдЦрд╛ рдерд╛ред рд╕рдВрдХреНрд╖реЗрдк рдореЗрдВ - рд╡реЗ SHA-2 (рд╣реИрд▓реЛ, NSA!) рд╕реЗ рд▓рд┐рдП рдЧрдП рд╣реИрдВ рдФрд░ рдПрдХ 32bit рд╕рдВрдЦреНрдпрд╛ рдХреЗ рджреВрд╕рд░реЗ рдореЗрдВ рдПрдХ рдЕрд╕реНрдкрд╖реНрдЯ рд░реВрдкрд╛рдВрддрд░рдг рдХрд╛ рдкреНрд░рддрд┐рдирд┐рдзрд┐рддреНрд╡ рдХрд░рддреЗ рд╣реИрдВред

рдореБрдЭреЗ рдЗрди рдХрд╛рд░реНрдпреЛрдВ рдореЗрдВ рд╕реНрдерд┐рд░рд╛рдВрдХ рдореЗрдВ рджрд┐рд▓рдЪрд╕реНрдкреА рдереА, рд╡реЗ рдХрд╣рд╛рдБ рд╕реЗ рдЖрдП рдереЗ рдФрд░ рдЙрдирдХреА рдЧрдгрдирд╛ рдХреИрд╕реЗ рдХреА рдЧрдИ рдереАред рдпрд╣ рдкрддрд╛ рдЪрд▓рд╛ рдХрд┐ рдЗрд╕рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ 0 рд╕реЗ рдЕрдзрд┐рдХ рдЬрд╛рдирдХрд╛рд░реА рд╣реИ, рдЬреЛ рдХрд┐ рдКрдкрд░ рджрд┐рдП рдЧрдП рд▓рд┐рдВрдХ рдореЗрдВ рджреА рдЧрдИ рд╣реИред рдореИрдВрдиреЗ рдЗрди рджреЛ рдХрд╛рд░реНрдпреЛрдВ рдХреА рдЕрд╡рдзрд┐ рдХреА рдЧрдгрдирд╛ рдХреА, рдпрд╣ рд╕рднреА рдХреА рдЕрдзрд┐рдХрддрдо рдирд╣реАрдВ рдереА рдФрд░ рдореИрдВрдиреЗ рдЙрди рд╕реНрдерд┐рд░рд╛рдВрдХ рдХреЛ рдЙрдард╛рдпрд╛ рдЬреЛ рдЕрдзрд┐рдХрддрдо рдЕрд╡рдзрд┐ рдХреЗ рдЕрдиреБрд░реВрдк рдереЗред рдПрдХ рд╕рд░рд▓ рдЪрдХреНрд░ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рддреЗ рд╣реБрдП, рддреАрдиреЛрдВ рд╕реНрдерд┐рд░рд╛рдВрдХ рдХреЗ рдорд╛рдзреНрдпрдо рд╕реЗ рдЫрдВрдЯрдиреА рдХрд░рддреЗ рд╣реБрдП, рдореИрдВрдиреЗ рдЙрди рддреНрд░рд┐рдЧреБрдгреЛрдВ рдХреА рдЦреЛрдЬ рдХреА рдЬрд┐рдирдореЗрдВ рдЕрд╡рдзрд┐ рдЕрдзрд┐рдХрддрдо рд╣реЛрдЧреАред рдЦреИрд░, рдореИрдВрдиреЗ рдРрд╕рд╛ рджреЗрдЦрд╛ рдХрд┐ рджреЛ рдЕрд▓рдЧ-рдЕрд▓рдЧ рддреНрд░рд┐рдЧреБрдгреЛрдВ рдХреЗ рдорд╛рди рдЕрд╡рдзрд┐ рдХреА рдЧрдгрдирд╛ рдХреЗ рджреМрд░рд╛рди рдкреНрд░рддрд┐рдЪреНрдЫреЗрдж рдирд╣реАрдВ рдХрд┐рдПред рдпрд╣рд╛рдБ, рдЙрджрд╛рд╣рд░рдг рдХреЗ рд▓рд┐рдП, рдРрд╕реЗ рддреНрд░рд┐рдЧреБрдг (рдРрд╕реА рдХрдИ рдЬреЛрдбрд╝рд┐рдпрд╛рдБ рд╣реИрдВ, рдореИрдВрдиреЗ рдЙрди рд▓реЛрдЧреЛрдВ рдХреЛ рдЪреБрдирд╛ рдЬреЛ рдореБрдЭреЗ рдкрд╕рдВрдж рдереЗ)ред
{22, 13, 3} рдФрд░ {18, 4, 9} рдореВрд▓ {7, 18, 3} рдХреЗ рдмрдЬрд╛рдп рдФрд░ {17, 19, 10}}

рдореБрдЭреЗ рдирд╣реАрдВ рдкрддрд╛ рдХрд┐ рдЗрди рдХрд╛рд░реНрдпреЛрдВ рдХреЗ рд╡рд┐рдХрд╛рд╕ рдореЗрдВ рдПрдирдПрд╕рдП рдХреЛ рдХреИрд╕реЗ рдирд┐рд░реНрджреЗрд╢рд┐рдд рдХрд┐рдпрд╛ рдЧрдпрд╛ рдерд╛, рд╢рд╛рдпрдж рдЙрдирдХреЗ рдкрд╛рд╕ рдПрдХ рдмреБрдХрдорд╛рд░реНрдХ рд╣реИ, рдпрд╛ рд╢рд╛рдпрдж рдирд╣реАрдВред рд▓реЗрдХрд┐рди рдпрд╣ рдмрд╣реБрдд рд╕рдВрднрд╛рд╡рдирд╛ рд╣реИ рдХрд┐ рдореЗрд░реЗ рд╕реНрдерд┐рд░рд╛рдВрдХ рдЙрдирдХреА рддреБрд▓рдирд╛ рдореЗрдВ рдмрджрддрд░ рдирд╣реАрдВ рд╣реИрдВред рд╡реЗ рдЕрд╕реНрд╡рд╛рднрд╛рд╡рд┐рдХ рдкрддреНрд░рд╛рдЪрд╛рд░ рднреА рдкреНрд░рджрд╛рди рдХрд░рддреЗ рд╣реИрдВ (рд╕рднреА рдорд╛рдиреЛрдВ рдХреЗ рд▓рд┐рдП рдЬрд╛рдБрдЪ рдХреА рдЬрд╛рддреА рд╣реИ 0 - (2 32 -1)) рдФрд░ рдЙрдирдХреЗ рдкрд╛рд╕ рдорд╛рдирдХ рд▓реЛрдЧреЛрдВ рдХреА рддреБрд▓рдирд╛ рдореЗрдВ рд▓рдВрдмрд╛ рдЪрдХреНрд░ рд╣реЛрддрд╛ рд╣реИред рдЗрд╕рд▓рд┐рдП, рдЙрдиреНрд╣реЗрдВ рдореЗрд░рд╛ рд╕рд╛рде рджреЗрдиреЗ рдХреЗ рд▓рд┐рдП рд╕реНрд╡рддрдВрддреНрд░ рдорд╣рд╕реВрд╕ рдХрд░реЗрдВ

  private static int f1(int x) { return rotateRight(x, 22) ^ rotateRight(x, 13) ^ (x >>> 3); } private static int f2(int x) { return rotateRight(x, 18) ^ rotateRight(x, 4) ^ (x >>> 9); } 


C рдпрд╣ рдкрддрд╛ рд▓рдЧрд╛ред

рдЕрдм рдПрдХ рдмрд╛рдд рдФрд░ред рдореБрдЭреЗ HC-128 рдХреЗ рдПрдХ рд╕рдВрдпреЛрдЬрди рд╡рд┐рд╢реНрд▓реЗрд╖рдг рдХреЗ рд╕рд╛рде рдПрдХ рджрд╕реНрддрд╛рд╡реЗрдЬ рдорд┐рд▓рд╛ред рдПрдХ рдЕрд░рдм рдордЯрд╛рдирд╛ рд╣реИ, рд▓реЗрдХрд┐рди рдЕрдзрд┐рдХ рджрд┐рд▓рдЪрд╕реНрдк рдмрд╛рдд рдпрд╣ рд╣реИ рдХрд┐ рдХрд╛рд░реНрдпреЛрдВ рдХреЛ рд╕реБрдзрд╛рд░рдиреЗ рдХреЗ рд▓рд┐рдП рд╕реБрдЭрд╛рд╡ рджрд┐рдП рдЧрдП рд╣реИрдВ h1 , h2 рдФрд░ g1 , g2 (рдзрд╛рд░рд╛ 4)

рд╕реБрдзрд╛рд░ рдХрд╛ рд╕рд╛рд░ рдЗрд╕ рдкреНрд░рдХрд╛рд░ рд╣реИ: рдПрдЪ 1 (рдПрдХреНрд╕) рдФрд░ рдПрдЪ 2 (рдПрдХреНрд╕) рдлрд╝рдВрдХреНрд╢рди рдЙрдирдХреЗ рджреНрд╡рд╛рд░рд╛ рдкреНрд░рджрд╛рди рдХрд┐рдП рдЧрдП 32 рдореЗрдВ рд╕реЗ рдХреЗрд╡рд▓ 16 рдмрд┐рдЯреНрд╕ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рддреЗ рд╣реИрдВред рдЗрди 16 рдмрд┐рдЯреНрд╕ рдХрд╛ рдЙрдкрдпреЛрдЧ рд░рд╛рдЬреНрдп рдЕрдиреБрдХреНрд░рдо рдкреА рдФрд░ рдХреНрдпреВ рдореЗрдВ 2 рдЗрдВрдбреЗрдХреНрд╕ (2x8) рдХреЗ рд░реВрдк рдореЗрдВ рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ ред рд▓реЗрдХрд┐рди рд╕рднреА 32 рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдирд╛ рдЖрд╡рд╢реНрдпрдХ рд╣реЛрдЧрд╛, рдЕрдиреНрдпрдерд╛ рдЖрдВрддрд░рд┐рдХ рд╕реНрдерд┐рддрд┐ рдХреЛ рдмрд╣рд╛рд▓ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдХреБрдЫ рд╢рд░реНрддреЛрдВ рдХреЗ рддрд╣рдд рд╕рдВрднрд╡ рд╣реИред рдЗрд╕рд▓рд┐рдП, рдЗрди рдХрд╛рд░реНрдпреЛрдВ рдореЗрдВ рд╢реБрд░реВ рдореЗрдВ рдХреНрдпрд╛ рд╕реЛрдЪрд╛ рдЧрдпрд╛ рд╣реИ (рджреЛ рддрддреНрд╡реЛрдВ рдХреЗ рдпреЛрдЧ 2 32 ) рдПрдХреНрд╕ рдХреЗ рд╕рд╛рде рд╣реА рдПрдХреНрд╕ рд╣реИред рдпрд╣ рдЗрд╕ рддрд░рд╣ рджрд┐рдЦреЗрдЧрд╛ (рдКрдкрд░ рд╡рд┐рдХрд▓реНрдк рдХреЗ рд╕рд╛рде рддреБрд▓рдирд╛ рдХрд░реЗрдВ):

  private int h1(int x) { return (q[x & 0xFF] + q[((x >> 16) & 0xFF) + 256]) ^ x; } private int h2(int x) { return (p[x & 0xFF] + p[((x >> 16) & 0xFF) + 256]) ^ x; } 


рдЕрдм рдХрд╛рд░реНрдпреЛрдВ рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ g1 (x) рдФрд░ g2 (x) ред рд░рд╛рдЬреНрдпреЛрдВ рдХреЗ P рдФрд░ Q рдПрдХ рджреВрд╕рд░реЗ рдХреЗ рд╕реНрд╡рддрдВрддреНрд░ рд░реВрдк рд╕реЗ рд░рд╣рддреЗ рд╣реИрдВред рдЗрд╕рд▓рд┐рдП, рдкреНрд░рддрд┐рдХреВрд▓ рдкрд░рд┐рд╕реНрдерд┐рддрд┐рдпреЛрдВ (рдЗрди рд╕рд░рдгрд┐рдпреЛрдВ рдореЗрдВ рд╕реЗ рдПрдХ рдХреА рдорд╛рдиреНрдпрддрд╛ рдФрд░ рдЙрддреНрдкрдиреНрди рдмрд╛рдЗрдЯреНрд╕ рдХреА рдзрд╛рд░рд╛ рдХрд╛ рд╣рд┐рд╕реНрд╕рд╛) рдХреЗ рддрд╣рдд рдпрд╣ рдЦрд░рд╛рдм рдкрд░рд┐рдгрд╛рдо рд╣реЛ рд╕рдХрддрд╛ рд╣реИред

рдЗрд╕рд▓рд┐рдП, рд╣рдо рдлрд╝рдВрдХреНрд╢рди рдЬреА 1 рдФрд░ рдЬреА 2 рдХреЛ рд╕рдВрд╢реЛрдзрд┐рдд рдХрд░рддреЗ рд╣реИрдВ рддрд╛рдХрд┐ рдкреА рдХрд╛ рдкреНрд░рддреНрдпреЗрдХ рддрддреНрд╡ рдХреНрдпреВ рдХреЗ рдпрд╛рджреГрдЪреНрдЫрд┐рдХ рддрддреНрд╡ рдкрд░ рдирд┐рд░реНрднрд░ рд╣реЛ рдФрд░ рдЗрд╕рдХреЗ рд╡рд┐рдкрд░реАрддред рдФрд░ рддрддреНрд╡ рд╡рд╛рдИ рдХреЛ рд╕реНрдерд╛рдирд╛рдВрддрд░рд┐рдд рдХрд░рдиреЗ рд╡рд╛рд▓реЗ рдЪрдХреНрд░реАрдп рдХреЗ рдмрдЬрд╛рдп , рд╣рдо рдПрд░реЗ рдХреЗ рдХреНрдпреВ рд╕реЗ рддрддреНрд╡ рдХреЗ рд▓рд┐рдП рдПрдХ рд╕реВрдЪрдХрд╛рдВрдХ рдХреЗ рд░реВрдк рдореЗрдВ рдЗрд╕рдореЗрдВ рд╕реЗ рдХреБрдЫ рдмрд┐рдЯреНрд╕ рд▓реЗрддреЗ рд╣реИрдВ ред

  private int g1(int x, int y, int z) { return (rotateRight(x, 10) ^ rotateRight(z, 23)) + Q[(y >> 7) & 0x1FF]; } private int g2(int x, int y, int z) { return (rotateLeft(x, 10) ^ rotateLeft(z, 23)) + P[(y >> 7) & 0x1FF]; } 


рдпрд╣ рд╕рдм рд╣реИ, рдЕрдм рд╣рдорд╛рд░реЗ рдкрд╛рд╕ рдПрдХ рдирдпрд╛ рдПрд▓реНрдЧреЛрд░рд┐рдереНрдо рд╣реИ рдЬреЛ рдореВрд▓ рдЗрди-рд▓рд╛рдЗрди HC-128 рдореЗрдВ рдЕрд╡рд░ (рдФрд░ рд╕рд┐рджреНрдзрд╛рдВрдд рд░реВрдк рдореЗрдВ, рд╢реНрд░реЗрд╖реНрда) рдирд╣реАрдВ рд╣реИред

рдЯрд┐рдкреНрдкрдгреА



рдмреЗрд╢рдХ, рдпрд╣ рд╕рдм рдЦреЗрд▓ рд╕реЗ рдмрдбрд╝рд╛ рд╣реИ, рдФрд░ рдореБрдЭреЗ рдмрд╕ рдЖрдкрдХреЛ рд╕рд▓рд╛рд╣ рджреЗрдиреА рдЪрд╛рд╣рд┐рдП рдХрд┐ рдЖрдк рд╡рд╛рд╕реНрддрд╡рд┐рдХ рдЕрдиреБрдкреНрд░рдпреЛрдЧреЛрдВ рдореЗрдВ рдРрд╕реА рдЪреАрдЬреЛрдВ рдХрд╛ рдЙрдкрдпреЛрдЧ рди рдХрд░реЗрдВ ред рд▓реЗрдХрд┐рди рджрд┐рдорд╛рдЧ рдХреЗ рд▓рд┐рдП рдПрдХ рдЖрд░реЛрдк рдХреЗ рд░реВрдк рдореЗрдВ, "рд╕реНрд╡рдпрдВ рдХреЗ рд▓рд┐рдП" рдФрд░ рдорд╛рдирдХреЛрдВ рдФрд░ рдкреЗрдЯреЗрдВрдЯ (рдЕрдЧрд░ рдПрдЪрд╕реА -128 рдХреЛ рдкреЗрдЯреЗрдВрдЯ рдХрд░рд╛рдпрд╛ рдЧрдпрд╛ рдерд╛) рдХреЗ рдЬрд╛рдирдмреВрдЭрдХрд░ рдЪреЛрд░реА, рдЗрд╕ рддрд░рд╣ рдХреЗ рдЕрдиреБрд╕рдВрдзрд╛рди рдФрд░ рд╕рдЯреАрдХ рд╕рдВрд╢реЛрдзрдиреЛрдВ рд╕реЗ рдЬреАрд╡рди рдХрд╛ рдЕрдзрд┐рдХрд╛рд░ рд╣реЛ рд╕рдХрддрд╛ рд╣реИред рдЙрджрд╛рд╣рд░рдг рдХреЗ рд▓рд┐рдП, рдореИрдВ рдкрд╛рд╕рд╡рд░реНрдб рд╣реИрд╢рд┐рдВрдЧ рдХреЛ рдзреАрдорд╛ рдХрд░рдиреЗ рдХреА рдкреНрд░рдХреНрд░рд┐рдпрд╛ рдореЗрдВ рдЗрд╕ рд╡рд┐рдХрд▓реНрдк рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рддрд╛ рд╣реВрдВ (рдореИрдВ рдкрд╛рд╕рд╡рд░реНрдб рдХреЗ 15 рд╣реИрд╢ (рдкрд╛рд╕рд╡рд░реНрдб) + рд╣реИрд╢ (рд╣реИрд╢ (рдкрд╛рд╕рд╡рд░реНрдб)) + (рд╣реИрд╢ (рдкрд╛рд╕рд╡рд░реНрдб) + рд╣реИрд╢ (рд╣реИрд╢ (рдкрд╛рд╕рд╡рд░реНрдб)) рдкрд╛рд╕рд╡рд░реНрдб 15 рд╕реЗ рдЙрддреНрдкрдиреНрди рдХрд░рддрд╛ рд╣реВрдВ ... ), рдореИрдВ рдЗрд╕ рд╕рд░рдгреА рд╕реЗ рд╕рдВрд╢реЛрдзрд┐рдд HC-128 рд╣реИрд╢ рдХреА рд╢реБрд░реБрдЖрдд рдХрд░рддрд╛ рд╣реВрдВ, рдФрд░ рдлрд┐рд░ рдЪрдХреНрд░ рдореЗрдВ рдХрдИ рдорд┐рд▓рд┐рдпрди рдмрд╛рд░ рдЗрд╕ рд╕рд░рдгреА рдХреЗ рд╡рд┐рднрд┐рдиреНрди рдЫреЛрдЯреЗ рд╣рд┐рд╕реНрд╕реЛрдВ рдХреЛ рд╕рдВрд╢реЛрдзрд┐рдд HC-128 рдХреЗ рд╕рд╛рде рдЕрдВрдд рдореЗрдВ рд╣реИрд╢ рд╕реЗ рдЧрдгрдирд╛ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП, рдЬреЛ рдзреАрдорд╛ рдкрд╛рд╕рд╡рд░реНрдб рд╣реИрд╢ рд╣реЛрдЧрд╛ред

рд╡реИрд╕реЗ, рдпрд╣ рдХреБрдЫ рд╣рдж рддрдХ рд╕реНрдкрдВрдЬ рдлрд╝рдВрдХреНрд╢рди рдХреА рдпрд╛рдж рджрд┐рд▓рд╛рддрд╛ рд╣реИред рд▓реЗрдХрд┐рди рдореИрдВ рдкрд╣рд▓реЗ рд╕реЗ рд╣реА рдбреЙрдкрд░ рдХреЗ рдмрд╛рджред

рдЗрд╕ рдЪрдХреНрд░ рдХреЗ рдмрд╛рдж, рдореИрдВ рдПрдХ рдмрд╛рд░ рдлрд┐рд░ рд╕рд░рдгреА рд╕реЗ рд╣реИрд╢ рдкрд░ рд╡рд┐рдЪрд╛рд░ рдХрд░рддрд╛ рд╣реВрдВ, рдпрд╣ рдПрдХ рдзреАрдорд╛ рдкрд╛рд╕рд╡рд░реНрдб рд╣реИрд╢ рд╣реЛрдЧрд╛ред рдЗрд╕ рддрд░рд╣ рдХреЗ рдЖрддрдВрдХ рдХреЗ рд▓рд┐рдП рдПрдХ рдкреНрд░рднрд╛рд╡реА рдЬрд╛рдирд╡рд░ рдмрд▓ рдХреЗрд╡рд▓ рд▓рд┐рдЦрдиреЗ рдХреЗ рд▓рд┐рдП рдЕрд╡рд╛рд╕реНрддрд╡рд┐рдХ рд╣реЛрдЧрд╛ред

рдпрд╣рд╛рдБ рдПрдХ рд╡рд░реНрдЧ рд╣реИ рдЬреЛ рдРрд╕рд╛ рдХрд░рддрд╛ рд╣реИред ObfuscatorEngine рдПрдХ рд╕рдВрд╢реЛрдзрд┐рдд HC-128 рд╣реИред рдПрдиреНрдЯреНрд░реЙрдкреА - рдПрдХ рд╕рд░рдгреА рдЬреЛ рд╣реИрд╢ рд╕реЗ рдПрдХрддреНрд░ рдХреА рдЬрд╛рддреА рд╣реИ, рдФрд░ рдлрд┐рд░ рдпрд╛рджреГрдЪреНрдЫрд┐рдХ рд╕реНрдерд╛рдиреЛрдВ рдореЗрдВ рдЯреБрдХрдбрд╝реЛрдВ рдХреЗ рд╕рд╛рде рдПрдиреНрдХреНрд░рд┐рдкреНрдЯ рдХреА рдЬрд╛рддреА рд╣реИред
рдкреБрдирд░рд╛рд╡реГрддреНрддрд┐рдпреЛрдВ рдХреА рд╕рдВрдЦреНрдпрд╛ рдПрдХ рдкреНрд░рдореБрдЦ рд╣реИред рдпрд╣ рдЙрд╕ рдЬрдЧрд╣ рдХреЛ рджреЗрдЦрдиреЗ рдХреЗ рд▓рд┐рдП рднреА рджрд┐рд▓рдЪрд╕реНрдк рд╣реИ рдЬрд╣рд╛рдВ рдСрдлрд╕реЗрдЯ рдХреА рдЧрдгрдирд╛ рдХреА рдЬрд╛рддреА рд╣реИред
SlowHasher
 package com.paranoim.crypto.utils; import java.util.Arrays; import org.bouncycastle.crypto.util.Pack; import com.paranoim.crypto.Consts; import com.paranoim.crypto.digest.SHA3_256; import com.paranoim.crypto.digest.SHA3_512; import com.paranoim.crypto.utils.obfuscator.ObfuscatorEngine; import fr.cryptohash.DigestEngine; import fr.cryptohash.Keccak256; import fr.cryptohash.Keccak512; /** * @author scratch * * @description this class does calculation of hash of a password but with many iterations, * so that it would be difficult to find with brute force * * @created 06.08.2010 */ public class SlowHasher { private static final int ITERATIONS_COUNT = 0x133ECD; private static final int CHUNK_SIZE = 71; public static byte[] calculateSlowHash(final String password, final byte[] salt) { if (salt.length != Consts.BIG_SALT_SIZE) { throw new IllegalArgumentException("Salt size must be " + Consts.BIG_SALT_SIZE + " bytes!"); } final byte[] saltedPassword = ByteUtils.concat(salt, password.getBytes()); final byte[] hashOfSaltedPassword = SHA3_512.process(saltedPassword); // hash of (salt+password) final ObfuscatorEngine engine = new ObfuscatorEngine(); // used to mix bytes //compute initial entropy string final byte[] entropy = getInitialEntropy(engine, hashOfSaltedPassword, saltedPassword); final byte[] entropyHash = SHA3_512.process(entropy); engine.init(entropyHash); // 16 bytes used as key, 16 as iv final int maxOffset = entropy.length - CHUNK_SIZE + 1; int offset = (Pack.bigEndianToInt(entropyHash, 7) & 0x7FFFFFFF) % maxOffset; // main loop for (int i = 0; i < ITERATIONS_COUNT; i++) { engine.processBytes(entropy, offset = (Pack.bigEndianToInt(entropy, offset) & 0x7FFFFFFF) % maxOffset, CHUNK_SIZE, entropy, offset); } //finalization process engine.init(SHA3_256.process(entropy)); engine.processBytes(entropy, 0, entropy.length, entropy, 0); engine.processBytes(entropyHash, 0, entropyHash.length, entropyHash, 0); return SHA3_256.process(ByteUtils.concat(entropyHash, entropy)); } private static byte[] getInitialEntropy(final ObfuscatorEngine engine, final byte[] hashOfSaltedPassword, final byte[] saltedPassword) { //final ExtendedDigest sha256 = new SHA3Digest(256); //final ExtendedDigest sha512 = new SHA3Digest(512); final DigestEngine sha256 = new Keccak256(); final DigestEngine sha512 = new Keccak512(); final byte[] hash32 = new byte[32]; final byte[] hash64 = new byte[64]; final byte[] sp = Arrays.copyOf(saltedPassword, saltedPassword.length); final byte[] h = Arrays.copyOf(hashOfSaltedPassword, hashOfSaltedPassword.length); byte[] entropy = ByteUtils.concat(h, sp); engine.init(hashOfSaltedPassword); engine.processBytes(entropy, 0, entropy.length, entropy, 0); for (int i = 0; i < hashOfSaltedPassword.length << 1; i++) // 128 iterations { final byte b = hashOfSaltedPassword[i >> 1]; // i/2 if (((b >> (i & 1)) & 1) == 1) // we check 1st bit of b on even i and 2nd on odd { engine.processBytes(sp, 0, sp.length, sp, 0); entropy = ByteUtils.concat(sp, entropy); hash(sha512, entropy, hash64); entropy = ByteUtils.concat(entropy, hash64); hash(sha256, entropy, hash32); engine.init(hash32); engine.processBytes(entropy, 0, entropy.length, entropy, 0); } else { engine.processBytes(h, 0, h.length, h, 0); entropy = ByteUtils.concat(entropy, h); hash(sha512, entropy, hash64); entropy = ByteUtils.concat(hash64, entropy); hash(sha256, entropy, hash32); engine.init(hash32); engine.processBytes(entropy, 0, entropy.length, entropy, 0); } } return entropy; } private static void hash(final DigestEngine digest, final byte[] data, final byte[] result) { digest.update(data, 0, data.length); digest.digest(result, 0, result.length); } } 



рдпрд╣рд╛рдБ рдЗрд╕ рддрд░рд╣ рдХреЗ рд╢реБрдХреНрд░рд╡рд╛рд░ рд╕реНрдХреЗрдЪ рд╣реИред

Source: https://habr.com/ru/post/In202210/


All Articles