Шифровка потока информации PHP-HTTP-Java (GNU-JCE, IAIK-JCE)

Apr 22, 2014 20:06

Это дополнение к моей предыдущей статье «Шифровка потока информации PHP-HTTP-Qt». Для того что бы понять о чём тут речь, прочитайте её сначала. Здесь приводится простенькая демонстрационная программа-клиент на Java, которая делает то же самое, что я сделал там на C++/Qt, то есть обеспечивает приём и расшифровку данных по тому же протоколу. Она работает с тем же самым серверным скриптом на PHP. Принятые расшифрованные данные (в моём случае XML) выводятся в стандартный поток вывода. Вот исходный код (URL-скрипта и пароли я естесвенно убрал):

import java.util.Arrays;

import java.util.HashMap;

import java.util.Map;

import java.lang.reflect.Array;

import java.io.*;

import java.net.*;

import java.security.*;

import javax.crypto.*;

import javax.crypto.spec.*;

import gnu.crypto.Registry;

import gnu.crypto.hash.MD5;

import gnu.crypto.jce.GnuCrypto;          // GNU-JCE  провайдер алгоритма TwoFish

// import iaik.security.provider.IAIK;    // IAIK-JCE провайдер алгоритма TwoFish

public class MainClass {

final static String surl = "http://......./xml.php"; // "baseurl()+"/xml.php";

final static String iv0  = "i.vector";

final static String key0 = ".............."; // Hex encoded

final static String password0 = "........."; // personal password in plain text

// prepare cipher

public static Cipher createCipher(int mode, byte[] key, byte[] ivBytes) throws

UnsupportedEncodingException,

NoSuchAlgorithmException,

NoSuchProviderException,

NoSuchPaddingException,

InvalidKeyException,

InvalidAlgorithmParameterException

{

IvParameterSpec iv = new IvParameterSpec(ivBytes);

SecretKey secretKey = new SecretKeySpec( key, "Twofish" );

// get Cipher and init it for encryption

//Cipher cipher = Cipher.getInstance("Twofish/CBC/NoPadding", "IAIK");       // IAIK

Cipher cipher = Cipher.getInstance("Twofish/CBC/NoPadding", Registry.GNU_CRYPTO);     // GNU

cipher.init( mode, secretKey, iv );

return cipher;

}

// encrypt string

public static String encrypt(String source, String key, byte[] iv)

throws

UnsupportedEncodingException,

InvalidKeyException,

IllegalBlockSizeException,

BadPaddingException,

NoSuchAlgorithmException,

NoSuchProviderException,

NoSuchPaddingException,

InvalidAlgorithmParameterException

{

Cipher cipher = createCipher( Cipher.ENCRYPT_MODE, key.getBytes("UTF-8"), iv );

// encrypt data

while ( source.length() % cipher.getBlockSize() !=0 ) source+="\0"; // padding

byte[] cipherText = cipher.doFinal( source.getBytes("UTF-8") );

// перевод cipherText в HEX-представление

String encryptedString = "";

for (int i = 0; i < cipherText.length; i++) {

encryptedString += String.format("%02x", cipherText[i]);

} // encryptedText = Base64Coder.encodeLines(encryptedText);

return encryptedString;

}

public static void main(String[] args) {

System.out.println("DecryptorTest HELLO");

// Security.addProvider( new IAIK() ); // using IAIK Security Provider

java.security.Security.addProvider(new GnuCrypto());

// Using Hex in Apache Commons:

// byte[] bytes = Hex.decodeHex(key0.toCharArray());

StringBuilder keyc = new StringBuilder();

for (int i = 0; i < key0.length(); i+=2) {

String str = key0.substring(i, i+2);

keyc.append((char)Byte.parseByte(str, 16));

}

System.out.println("DecryptorTest: Common secret key (plain) =" + keyc);

MD5 md5 = new MD5();

//IMessageDigest md5 = HashFactory.getInstance("MD5");

byte[] iv;

try {

iv = iv0.getBytes( "UTF-8" );

} catch (UnsupportedEncodingException e1) {

System.out.println("DecryptorTest: Error: UnsupportedEncodingException (UTF-8)");

return;

}

System.out.println("DecryptorTest: Common initialization vector length (bytes) =" + iv.length);

md5.update(iv, 0, iv.length);

String ivh = "";

iv = md5.digest();

for (int i = 0; i < iv.length; i++) {

ivh += String.format("%02x", iv[i] );

}

System.out.println("DecryptorTest: Common initialization vector (MD5) =" + ivh);

// encrypt the user password and convert it to Hex

String passwordh;

try {

passwordh = encrypt( password0, keyc.toString(), iv );

} catch ( InvalidKeyException

| UnsupportedEncodingException

| IllegalBlockSizeException

| BadPaddingException

| NoSuchAlgorithmException

| NoSuchProviderException

| NoSuchPaddingException

| InvalidAlgorithmParameterException e)

{

System.out.println("DecryptorTest: Error: cannot encrypt user password! Exception="+e.toString());

return;

}

System.out.println("DecryptorTest: Personal password (encripted, hex) =" + passwordh);

md5.reset();

try {

md5.update(password0.getBytes("UTF-8"), 0, password0.getBytes("UTF-8").length);

} catch (UnsupportedEncodingException e) {

System.out.println("DecryptorTest: Error: cannot prepare password (no UTF-8 encoding)");

return;

}

byte[] pwd5 = md5.digest();

//System.out.println("DecryptorTest: Personal password (MD5, hex) =" + password5);

int keysize;

keysize = 32; // Cipher.getMaxAllowedKeyLength("Twofish/CBC/NoPadding");

System.out.println("DecryptorTest: maximum key size ="+keysize );

URL url;

try {

url = new URL(surl);

} catch (MalformedURLException e) {

System.out.println("DecryptorTest: Error: Malformed URL");

return;

}

HttpURLConnection conn;

InputStream stream;

try {

conn = (HttpURLConnection) url.openConnection();

String post;

post = "user=shestero";

post+= "&password="+passwordh;

conn.setDoOutput(true); // мы будем писать POST данные

conn.setDoInput(true);

OutputStreamWriter out =

new OutputStreamWriter( conn.getOutputStream(), "UTF-8" );

out.write(post);

// out.write("\r\n"); // перевод строки попадает в значения, передаваемые POST-ом

out.close();

stream = conn.getInputStream();

stream.mark(1);

int i0 = 0;//stream.read();

BufferedReader r;

if (i0==0)

{

stream.skip(32); // skip header

// encrypted

System.out.println("DecryptorTest: Note: data comes encrypted!");

byte[] key2 = new byte[32];

Arrays.fill(key2,(byte)0);

int j=0;

for (int i=0; i() || i)

{

if (i()) key2[j++]=keyc.toString().substring(i,i+1).getBytes()[0];

if (i) key2[j++]=pwd5[i];

if (j>=keysize)

break;

}

System.out.println("DecryptorTest: Personal key to decript reply =["+key2+"]");

// TODO: Fix key size

if (j<=16) j=16; else if (j<=24) j=24; else if (j<32) j=32;

System.out.println("DecryptorTest: key2.length="+j);

Cipher cipher = createCipher( Cipher.DECRYPT_MODE, key2, iv );

r = new BufferedReader( new InputStreamReader( new CipherInputStream( stream, cipher ) ) );

}

else

{

// plain

stream.reset();

r = new BufferedReader( new InputStreamReader( stream ) );

System.out.println("DecryptorTest: Warning: data comes unencrypted!");

}

// Чтение строка за строкой для проверки

System.out.println("====[REPLY FROM SERVER:]===========================");

String inputLine;

while ((inputLine = r.readLine()) != null)

{

System.out.println(inputLine);

}

r.close();

System.out.println("====[SUCESS]=======================================");

} catch (IOException e) {

System.out.println("DecryptorTest: Error: IOException; URL="+surl);

} catch ( InvalidKeyException

|  NoSuchAlgorithmException

|  NoSuchProviderException

|  NoSuchPaddingException

|  InvalidAlgorithmParameterException e)

{

System.out.println("DecryptorTest: Error: cannot decode: Exception="+e.toString());

}

System.out.println("DecryptorTest BYE");

}

}
Исходник обработан: Java2html
Ради алгоритма Twofish я использовал из GNU-JCE , а также пробовал коммерческий IAIK с закрытым исходным кодом.

См. также: http://www.cryptix.org , http://bouncycastle.org
(
Comments
|Comment on this)

gnu, it, java, cryptography, jce, twofish, php, iaik

Previous post Next post
Up