/*
 * @(#)DHTest.java
 *
 * Copyright (C) 2007 Infocity Inc. All Rights Reserved.
 */
package info.dragonlady.crypto;

import java.security.*;
import java.security.spec.*;

import javax.crypto.*;
import javax.crypto.spec.*;

import javax.crypto.interfaces.*;

/**
 * TODO ƒNƒ‰ƒXŠT—v
 * 
 * @author Hiroshi.Ebata(INFOCITY)
 * @version $Revision: 1.0 $ $Date: 2007/03/30 19:14:11 $
 */
public class DHTest {

	public DHTest() {
		
	}

	public class Alice {
	    private Bob bob_;
	    private SecretKey secretKey_;
	    private byte[] secretKeyByte_;

	    public Alice(Bob bob) {
	        bob_ = bob;
	    }

	    public void generateSecretKey() throws Exception {
	        AlgorithmParameterGenerator paramGen = AlgorithmParameterGenerator
	            .getInstance("DH");
	        paramGen.init(512);
	        AlgorithmParameters params = paramGen.generateParameters();
	        DHParameterSpec dhSkipParamSpec = (DHParameterSpec)params
	            .getParameterSpec(DHParameterSpec.class);

	        KeyPairGenerator keyPairGen = KeyPairGenerator.getInstance("DH");
	        keyPairGen.initialize(dhSkipParamSpec);
	        KeyPair keyPair = keyPairGen.generateKeyPair();

	        KeyAgreement keyAgree = KeyAgreement.getInstance("DH");
	        keyAgree.init(keyPair.getPrivate());

	        X509EncodedKeySpec x509KeySpec = new X509EncodedKeySpec(bob_
	            .createPublicKeyEncode(keyPair.getPublic().getEncoded()));
	        PublicKey destinationPubKey = KeyFactory.getInstance("DH")
	            .generatePublic(x509KeySpec);
	        keyAgree.doPhase(destinationPubKey, true);

	        bob_.setKeyLength(keyAgree.generateSecret().length);
	        keyAgree.doPhase(destinationPubKey, true);
	        secretKeyByte_ = keyAgree.generateSecret();
	        keyAgree.init(keyPair.getPrivate());
	        keyAgree.doPhase(destinationPubKey, true);
	        secretKey_ = keyAgree.generateSecret("Blowfish");
	    }

	    public SecretKey getSecretKey() {
	        return secretKey_;
	    }

	    public byte[] getSecretKeyByte() {
	        return secretKeyByte_;
	    }
	}

	public class Bob {
	    private SecretKey secretKey_;
	    private KeyAgreement keyAgree_;
	    private PublicKey publicKey_;
	    private byte[] secretKeyByte_;

	    public Bob() {
	    }

	    public byte[] createPublicKeyEncode(byte[] pubKeyEnc) throws Exception {
	        X509EncodedKeySpec x509KeySpec = new X509EncodedKeySpec(pubKeyEnc);
	        publicKey_ = KeyFactory.getInstance("DH").generatePublic(x509KeySpec);

	        DHParameterSpec dhParamSpec = ((DHPublicKey)publicKey_).getParams();
	        KeyPairGenerator keyPairGen = KeyPairGenerator.getInstance("DH");
	        keyPairGen.initialize(dhParamSpec);
	        KeyPair keyPair = keyPairGen.generateKeyPair();

	        keyAgree_ = KeyAgreement.getInstance("DH");
	        keyAgree_.init(keyPair.getPrivate());

	        return keyPair.getPublic().getEncoded();
	    }

	    public void setKeyLength(int len) throws Exception {
	        byte[] secret = new byte[len];
	        int myLen;
	        try {
	            keyAgree_.doPhase(publicKey_, true);
	            myLen = keyAgree_.generateSecret(secret, 1);
	        } catch (ShortBufferException e) {
	            System.out.println(e.getMessage());
	        }
	        myLen = keyAgree_.generateSecret(secret, 0);
            System.out.println("mylen:" + myLen);
            System.out.println("secret:" + toHexString(secret));
	        keyAgree_.doPhase(publicKey_, true);
//	        secretKey_ = keyAgree_.generateSecret("DES");
	        secretKeyByte_ = keyAgree_.generateSecret();
	    }

	    public SecretKey getSecretKey() {
	        return secretKey_;
	    }
	    public byte[] getSecretKeyByte() {
	        return secretKeyByte_;
	    }
	}

	public static void main(String[] args) throws Exception {
		DHTest test = new DHTest();
	    Bob bob = test.new Bob();
	    Alice alice = test.new Alice(bob);
	    alice.generateSecretKey();

	    System.out.println("Alice secret: "
	            + toHexString(alice.getSecretKey().getEncoded()));
//	    System.out.println("Bob secret: "
//	            + toHexString(bob.getSecretKey().getEncoded()));
	    System.out.println("Alice secret: "
	            + toHexString(alice.getSecretKeyByte()));
	    System.out.println("Bob secret: "
	            + toHexString(bob.getSecretKeyByte()));
	}

	private static String toHexString(byte[] arr) {
	    StringBuffer buf = new StringBuffer();

	    for (int i = 0; i < arr.length; i++) {
	        buf.append(Integer.toHexString(arr[i] & 0xff));
	    }
	    return buf.toString();
	}

}
