对不起我的英语。
我尝试用AES-256为大学项目实现EKE。 主要的问题是,当客户端调用writeObject()到服务器时,最后一个接收到一个错误的对象,其中不同的chipertext表示不同的iv。
这是客户Alice:
package Secondo;
import java.math.BigInteger;
import javax.crypto.SecretKey;
import javax.crypto.SecretKeyFactory;
import java.security.*;
import java.io.*;
import java.net.*;
import javax.crypto.spec.PBEKeySpec;
import javax.crypto.spec.SecretKeySpec;
import javax.crypto.*;
import java.security.spec.KeySpec;
import java.net.Socket;
import javax.crypto.spec.IvParameterSpec;
import javax.xml.bind.DatatypeConverter;
/**
*
* @author Bazzotti
*
* Alice.
*
* rappresenta il client che si vuole autenticare al Server
*
*/
public class Alice
{
public static final int JabberServerPORT = 9999;
//public static final byte[] JabberServerADDRESS = new byte[]{127,0,0,1};
public static void main(String[] args) throws Exception {
// p è un numero primo in modo che qualsiasi g possa generare un insieme abbastanza grande
// inoltre perchè Diffie-Helman sia sicuro anche ((p-1)/2) deve essere primo
int bitLength = 512;
SecureRandom rnd = new SecureRandom();
//Attributi per DH
BigInteger p;
BigInteger g = new BigInteger(bitLength, rnd);
BigInteger Sa=new BigInteger(bitLength, rnd);
do{
p = g.max(Sa).nextProbablePrime();
} while (p.subtract(BigInteger.ONE).shiftRight(1).isProbablePrime(50));
BigInteger Ta=g.modPow(Sa,p);
//
String Alice=MyUtil.leggiString("inserisci il nome");
String password=MyUtil.leggiString("inserisci la password");
// System.out.println("stringa del BigInteger Ta "+Ta.toString());
System.out.println("lunghezza bit Ta"+Ta.bitCount()+"lunghezza bit p"+p.bitCount());
DatiChipertext prima_cifratura= cifraturaAES( chiaveAES(password),Ta.toByteArray());
byte[] A=prima_cifratura.getChipertext();
byte[] iv=prima_cifratura.getIv();
Socket socket=null;
System.out.println(Alice+","+A+","+g+p+","+iv);
try {
socket = new Socket("localhost", JabberServerPORT);
ObjectOutputStream out = new ObjectOutputStream(socket.getOutputStream());
out.flush();
ObjectInputStream in = new ObjectInputStream(socket.getInputStream());
System.out.println("mi sto connettendo al server");
// System.out.println("lunghezza primo messaggio "+primo_messaggio.length());
// Invio di A Alice g p
// System.out.println("lunghezza A"+A.length());
// System.out.println("chiave primo messaggio"+password);
PrimoMessaggioAlice primo_messaggio= new PrimoMessaggioAlice(Alice,A,g,p,iv);
out.writeObject(primo_messaggio);
out.reset();
System.out.println("primo messaggio inviato");
// Ricezione di Bob e B
PrimoMessaggioBob primo_messaggio_ricevuto = (PrimoMessaggioBob)in.readObject();
System.out.println("primo messaggio ricevuto");
// Decifro ottenendo Tb e c1
String Bob=primo_messaggio_ricevuto.getBob();
byte[] iv2=primo_messaggio_ricevuto.getIv();
byte[] B=primo_messaggio_ricevuto.getB();
System.out.println("B ricevuto "+B+" iv "+iv2);
/**Cipher mDecipher = Cipher.getInstance ("AES/CBC/PKCS5Padding");
mDecipher.init (Cipher.DECRYPT_MODE, chiaveAES(password));
*/
byte[] B_decriptato=decifraturaAES(chiaveAES(password),B,iv2);
byte[] c1= new byte [4];
byte[] Tb_decriptato= new byte[B_decriptato.length-4];
for(int i=0;i<B_decriptato.length;i++)
{
if(i<(B_decriptato.length-4))
Tb_decriptato[i]=B_decriptato[i];
else
c1[i]=B_decriptato[i];
}
//Sostituito con Tb dato da bob
BigInteger Tb=new BigInteger(Tb_decriptato);
//
//Chiave per i metodi successivi
BigInteger Kt=Tb.modPow(Sa,p);
byte[] c2=(SecureRandom.getSeed(4));
//creazione della chiave effimera
byte[] secondo_messaggio=concat(c1,c2);
SecretKeySpec ephimeral_key= new SecretKeySpec(Kt.toByteArray(),"AES");
// System.out.println("lunghezza Kt "+Kt.bitLength()+"lunghezza p "+p.bitLength());
DatiChipertext secondo_messaggio_chipertext=cifraturaAES(ephimeral_key,secondo_messaggio);
byte[] secondo_messaggio_criptato=secondo_messaggio_chipertext.getChipertext();
byte[] iv3=secondo_messaggio_chipertext.getIv();
System.out.println(iv3);
// System.out.println("secondo messaggio inviato "+secondo_messaggio_criptato.getBytes()+"ephimeral key "+Kt.toByteArray());
/**System.out.println("Tb "+Tb.toString()+" Ta "+Ta.toString());
*/
SecondoMessaggioA secondo_messaggio_da_inviare=new SecondoMessaggioA(secondo_messaggio_criptato,iv3);
/**
* Invio del secondo messaggi ocriptato
*/
System.out.println("secondo messaggio inviato "+secondo_messaggio_da_inviare.getC1C2()+secondo_messaggio_da_inviare.getIv());
out.writeObject(secondo_messaggio_da_inviare);
out.flush();
/**
* Ricezione di c2'
*/
System.out.println("secondo messaggio inviato ");
SecondoMessaggioBob secondo_messaggio_ricevuto= (SecondoMessaggioBob)in.readObject();
System.out.println("secondo messaggio ricevuto ");
System.out.println(secondo_messaggio_ricevuto);
/**
* Verifica che c2 sia uguale a c2'
*/
/* Cipher mDecipher2 = Cipher.getInstance ("AES/CBC/PKCS5Padding");
mDecipher2.init (Cipher.DECRYPT_MODE, chiaveAES(Kt.toByteArray().toString()));
*/
byte[] iv4=secondo_messaggio_ricevuto.getIv();
byte[] c2_cifrato=secondo_messaggio_ricevuto.getC2();
byte[] c2_ricevuto=decifraturaAES(ephimeral_key,c2_cifrato,iv4);
if(c2_ricevuto.equals(c2))
System.out.println("Server Autenticato");
else
System.out.println("Server NON Autenticato");
}finally {
System.out.println("********** Chiudo il socket...");
try {
socket.close();
} catch (Exception e) {
System.out.println("********** Eccezione b" + e);
}
}
}
private static DatiChipertext cifraturaAES (SecretKey secret, byte[] messaggio) throws Exception
{
//cifratura
Cipher mEcipher = Cipher.getInstance ("AES/CBC/PKCS5Padding");
/* byte[] iv = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
IvParameterSpec ivspec = new IvParameterSpec(iv);
mEcipher.init (Cipher.ENCRYPT_MODE, secret,ivspec);
*/
mEcipher.init (Cipher.ENCRYPT_MODE, secret);
AlgorithmParameters params = mEcipher.getParameters();
byte []iv = params.getParameterSpec(IvParameterSpec.class).getIV();
System.out.println("iv usato "+iv);
// byte[] messaggio_da_codificare = DatatypeConverter.parseBase64Binary(messaggio);
//chipertext è ok lungo 80 byte
//String stringa_cifrata=new String (chiphertext);
//Devono essere 80 caratteri o un multiplo
//System.out.println("lunghezza caratteri stringa messaggio"+stringa_cifrata.length());
return new DatiChipertext (messaggio,iv);
}
private static SecretKey chiaveAES (String chiave) throws Exception
{
//creazione della chiave
//SecretKeyFactory factory = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA1");
// byte [] salt={0,0,0,0,0,0,0,0};
// SecretKeySpec tmp = new SecretKeySpec (chiave.getBytes("UTF-8"),"AES");
// SecretKey tmp = factory.generateSecret (spec);
//calcolo sha-256 della chiave
MessageDigest digest = MessageDigest.getInstance("SHA-256");
byte[] hash = digest.digest(chiave.getBytes());
SecretKey secret = new SecretKeySpec (hash, "AES");
return secret;
}
private static byte[] decifraturaAES (SecretKey chiave, byte[] messaggio, byte[] iv) throws Exception
{
Cipher mDecipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
IvParameterSpec ivspec = new IvParameterSpec(iv);
mDecipher.init (Cipher.DECRYPT_MODE, chiave,ivspec);
// byte [] messaggio_da_decodificare=DatatypeConverter.parseBase64Binary(messaggio);
// System.out.println("lunghezza byte chiper"+messaggio_da_decodificare.length);
//byte [] messaggio_da_decodificare=messaggio.getBytes("UTF-8");
return mDecipher.doFinal(messaggio);
}
public static byte[] concat(byte[] a, byte[] b) {
int aLen = a.length;
int bLen = b.length;
byte[] c= new byte[aLen+bLen];
System.arraycopy(a, 0, c, 0, aLen);
System.arraycopy(b, 0, c, aLen, bLen);
return c;
}
}
&#13;
这是服务器Bob:
package Secondo;
import java.math.BigInteger;
import javax.crypto.Cipher;
import javax.crypto.SecretKey;
import javax.crypto.SecretKeyFactory;
import javax.xml.bind.DatatypeConverter;
import java.security.MessageDigest;
import java.security.SecureRandom;
import java.io.*;
import java.net.*;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.PBEKeySpec;
import javax.crypto.spec.SecretKeySpec;
import java.security.spec.KeySpec;
import java.net.Socket;
import java.math.BigInteger;
import javax.crypto.SecretKey;
import javax.crypto.SecretKeyFactory;
import java.security.*;
import java.io.*;
import java.net.*;
import javax.crypto.spec.PBEKeySpec;
import javax.crypto.spec.SecretKeySpec;
import javax.crypto.*;
import java.security.spec.KeySpec;
import java.net.Socket;
import javax.crypto.spec.IvParameterSpec;
import javax.xml.bind.DatatypeConverter;
/**
*
* @author Bazzotti
*
* Bob.
*
* rappresenta il Server che deve autenticare il Client
*
*/
public class Bob
{
private static String Bob ="Bob";
public static final int JABBERSERVERPORT = 9999;
public static void main(String[] args) throws Exception {
Utenti utenti=new Utenti();
utenti.inizzializzazioneUtenti();
ServerSocket ServS = new ServerSocket(JABBERSERVERPORT);
Socket socket = null;
int bitLength = 256;
SecureRandom rnd = new SecureRandom();
try {
socket = ServS.accept();
ObjectOutputStream out = new ObjectOutputStream(socket.getOutputStream());
out.flush();
ObjectInputStream in = new ObjectInputStream(socket.getInputStream());
/**
* Ricezione della stringa
*/
System.out.println("sto aspettando la connessione");
PrimoMessaggioAlice primo_messaggio_ricevuto=(PrimoMessaggioAlice)in.readObject() ;
// System.out.println(Alice_A_g_p.length);
String Alice =primo_messaggio_ricevuto.getAlice();
String password =utenti.cerca(Alice);
byte[] iv1=primo_messaggio_ricevuto.getIv();
BigInteger p= primo_messaggio_ricevuto.getP();
BigInteger g= primo_messaggio_ricevuto.getG();
byte[] A=primo_messaggio_ricevuto.getA();
//creazione della chiave
SecretKey chiave=chiaveAES (password);
System.out.println(" A è "+A+" iv byte "+iv1);
//Decodifica di A
// System.out.println("chiave primo messaggio"+password);
BigInteger Ta=new BigInteger(decifraturaAES(chiave,A,iv1));
// byte [] salt =Alice_A_g_p_salt[4].getBytes("UTF-8");
//Calcolo Tb
byte[] c1=(SecureRandom.getSeed(4));
BigInteger Sb=new BigInteger(bitLength-1, rnd);
BigInteger Tb=g.modPow(Sb,p);
//Crittografo messaggio
byte[] primo_messaggio_da_crittografare=concat(Tb.toByteArray(),c1);
// System.out.println("Tb, c1"+primo_messaggio_da_crittografare.getBytes());
DatiChipertext primo_chipertext=cifraturaAES(chiaveAES(password),primo_messaggio_da_crittografare);
byte[] B=primo_chipertext.getChipertext();
byte[] iv2=primo_chipertext.getIv();
PrimoMessaggioBob Bob_B= new PrimoMessaggioBob(Bob,B,iv2);
// System.out.println(" B "+B.getBytes());
//System.out.println("Bob, B byte "+primo_messaggio_inviato);
// System.out.println("Bob, B stringa "+Bob_B.getBytes()+"\n iv "+iv);
//Chiave per i metodi successivi
BigInteger Kt=Ta.modPow(Sb,p);
/**
* Invio di Tb e Bob
*/
out.writeObject(Bob_B);
out.flush();
System.out.println("primo messaggio inviato");
/**
* Ricevo secondo messaggio c1 e c2
*/
SecondoMessaggioA secondo_messaggio_ricevuto=(SecondoMessaggioA)in.readObject();
System.out.println("secondo messaggio ricevuto");
//Decodifico c1 e c2
/**
* Trasformazione in stringa non corretta, oppure dimensione non va bene
*/
System.out.println("lunghezza Kt "+Kt.bitLength()+"lunghezza p "+p.bitLength());
SecretKeySpec ephimeral_key= new SecretKeySpec(Kt.toByteArray(),"AES");
// System.out.println("secondo messaggio ricevuto "+secondo_messaggio_ricevuto_stringa.getBytes()+"ephimeral key "+Kt.toByteArray());
// System.out.println("Tb "+Tb.toString()+" Ta "+Ta.toString());
byte[] iv3=secondo_messaggio_ricevuto.getIv();
System.out.println(iv3);
byte[] secondo_messaggio_da_decodificare=secondo_messaggio_ricevuto.getC1C2();
byte[] c1_c2=decifraturaAES(ephimeral_key,secondo_messaggio_da_decodificare,iv3);
byte[] c1_ricevuto=new byte[4];
byte[] c2=new byte[4];
for (int i=0;i<4;i++)
{
c1_ricevuto[i]=c1_c2[i];
}
for (int i=4;i<9;i++)
{
c2[i]=c1_c2[i];
}
if(c1_ricevuto.equals(c1))
{
System.out.println("Autenticato il client");
DatiChipertext secondo_messaggio_criptato=cifraturaAES(ephimeral_key,c2);
byte[] c2_criptato=secondo_messaggio_criptato.getChipertext();
byte[] iv4=secondo_messaggio_criptato.getIv();
SecondoMessaggioBob secondo_messaggio_da_inviare=new SecondoMessaggioBob(c2_criptato,iv4);
/**
* invio di c2
*/
out.writeObject(secondo_messaggio_da_inviare);
out.flush();
}
else
System.out.println("client sbagliato");
}finally {
System.out.println("********** Chiudo il socket...");
try {
socket.close();
} catch (Exception e) {
System.out.println("********** Eccezione b" + e);
}
ServS.close();
}
}
private static DatiChipertext cifraturaAES (SecretKey secret, byte[] messaggio) throws Exception
{
//cifratura
Cipher mEcipher = Cipher.getInstance ("AES/CBC/PKCS5Padding");
/* byte[] iv = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
IvParameterSpec ivspec = new IvParameterSpec(iv);
mEcipher.init (Cipher.ENCRYPT_MODE, secret,ivspec);
*/
mEcipher.init (Cipher.ENCRYPT_MODE, secret);
AlgorithmParameters params = mEcipher.getParameters();
byte []iv = params.getParameterSpec(IvParameterSpec.class).getIV();
System.out.println("iv usato "+iv);
// byte[] messaggio_da_codificare = DatatypeConverter.parseBase64Binary(messaggio);
//chipertext è ok lungo 80 byte
//String stringa_cifrata=new String (chiphertext);
//Devono essere 80 caratteri o un multiplo
//System.out.println("lunghezza caratteri stringa messaggio"+stringa_cifrata.length());
return new DatiChipertext (messaggio,iv);
}
private static SecretKey chiaveAES (String chiave) throws Exception
{
//creazione della chiave
//SecretKeyFactory factory = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA1");
// byte [] salt={0,0,0,0,0,0,0,0};
// SecretKeySpec tmp = new SecretKeySpec (chiave.getBytes("UTF-8"),"AES");
// SecretKey tmp = factory.generateSecret (spec);
//calcolo sha-256 della chiave
MessageDigest digest = MessageDigest.getInstance("SHA-256");
byte[] hash = digest.digest(chiave.getBytes());
SecretKey secret = new SecretKeySpec (hash, "AES");
return secret;
}
private static byte[] decifraturaAES (SecretKey chiave, byte[] messaggio, byte[] iv) throws Exception
{
Cipher mDecipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
IvParameterSpec ivspec = new IvParameterSpec(iv);
mDecipher.init (Cipher.DECRYPT_MODE, chiave,ivspec);
// byte [] messaggio_da_decodificare=DatatypeConverter.parseBase64Binary(messaggio);
// System.out.println("lunghezza byte chiper"+messaggio_da_decodificare.length);
//byte [] messaggio_da_decodificare=messaggio.getBytes("UTF-8");
return mDecipher.doFinal(messaggio);
}
public static byte[] concat(byte[] a, byte[] b)
{
int aLen = a.length;
int bLen = b.length;
byte[] c= new byte[aLen+bLen];
System.arraycopy(a, 0, c, 0, aLen);
System.arraycopy(b, 0, c, aLen, bLen);
return c;
}
}
&#13;
我传递的对象是PrimoMessaggioAlice(FirstMessageFromAlice)
package Secondo;
import java.math.*;
import java.io.*;
public class PrimoMessaggioAlice implements Serializable {
/**
*
*/
private static final long serialVersionUID = 1L;
private String Alice;
private byte[] A;
private BigInteger g;
private BigInteger p;
private byte [] iv;
public PrimoMessaggioAlice(String _Alice, byte[] _A, BigInteger _g, BigInteger _p, byte[] _iv)
{
Alice=_Alice;
A=_A;
g=_g;
p=_p;
iv=_iv;
}
public String getAlice()
{
return Alice;
}
public byte[] getA()
{
return A;
}
public byte[] getIv()
{
return iv;
}
public BigInteger getP()
{
return p;
}
public BigInteger getG()
{
return g;
}
}
&#13;
在客户端和服务器中都是一样的。
当Alice发送PrimoMessaggioAlice时(A = [B @ 6e56ae和iv = [B @ 1b3967]) 鲍勃通常阅读PrimoMessaggioAlice(A = [B @ 19e8f17和iv = [B @ c44b88]
感谢帮助