package ssh;

import ssh.RSA.*;
import Tools.*;
import sdsi.*;
import proof.*;
import jp.Tool;
import java.io.*;

/**
 * This class is analogous to PureTLS' SSLContext for SSL channels. It
 * is an object that carries the state needed to connect and accept SSH
 * channels. It has its own RSA public/private key pair, and a reference
 * to a source of randomness.
 */
public class SSHContext {
	SshRandom random;		// source of random bits

	RSAKey privateKey;		// keys for local end of connection
	RSAKey publicKey;

	public SDSIRSAPublicKey getPublicKey() {
		return new SDSIRSAPublicKey(publicKey);
	}

	// TODO gaping security hole?
	public SDSIRSAPrivateKey getPrivateKey() {
		return new SDSIRSAPrivateKey(privateKey);
	}

	/**
	 * Get an anonymous context. Tries to use the context associated
	 * with this thread; otherwise creates a new default context.
	 */
	public static SSHContext getDefault() {
		SSHContext context = (SSHContext) contextByThread.get();
		if (context==null) {
			// create a new context with its own key and stash that.
			context = loadKeys();	// TODO: make the loadKeys cheat a switch
			contextByThread.setDefault(context);
			contextByThread.set(context);
		}
		return context;
	}

	static SSHContext loadKeys() {
		try {
			String filename = "certs-client/0.keypair";
			System.err.println("Cheating on creating a pub/priv "
				+"keypair by loading "+filename);
			SDSIKeyPair kp = (SDSIKeyPair) KeyTools.processFilename(filename);
			RSAKey rsaPublicKey = RSAKey.fromRSAPublicKey(
				(java.security.interfaces.RSAPublicKey) kp.getPublicKey());
			RSAKey rsaPrivateKey = RSAKey.fromRSAPrivateKey(
				(java.security.interfaces.RSAPrivateKey) kp.getPrivateKey());
			return new SSHContext(rsaPrivateKey, rsaPublicKey);
		} catch (FileNotFoundException ex) {
			System.err.println("Can't cheat ("+ex.toString()
				+"), so making a new keypair.");
			return newKeys();
		}
	}

	public static SSHContext newKeys() {
		// build a key pair and a context
		SDSIKeyPair skp;
		log.setPrefix("test: ").log("default", "creating key...");
		try {
			skp = Tool.generateKeyPair();
		} catch (java.security.NoSuchAlgorithmException ex) {
			throw new RuntimeException(ex.toString());
		}
		log.log("default", "...key done.");

		RSAKey rsaPublicKey = RSAKey.fromRSAPublicKey(
			(java.security.interfaces.RSAPublicKey) skp.getPublicKey());
		RSAKey rsaPrivateKey = RSAKey.fromRSAPrivateKey(
			(java.security.interfaces.RSAPrivateKey) skp.getPrivateKey());
		return new SSHContext(rsaPrivateKey, rsaPublicKey);
	}

	public static PerThread contextByThread;
	static Log log = new Log();
	static {
		contextByThread = new PerThread();
		log.addLevel("default");
	}

	public SSHContext(RSAKey privateKey, RSAKey publicKey) {
		random = new SshRandom();
			// TODO: use JCE Randomness provider. This code predates JCE.
		this.privateKey = privateKey;
		this.publicKey = publicKey;
	}

	public void setKey(RSAKey[] pair) {
		setKey(pair[0], pair[1]);
	}

	public void setKey(RSAKey privateKey, RSAKey publicKey) {
		this.privateKey = privateKey;
		this.publicKey = publicKey;
	}

	public SDSIRSAPublicKey getSDSIRSAPublicKey() {
		return new SDSIRSAPublicKey(publicKey);
	}

	public SDSIRSAPrivateKey getSDSIRSAPrivateKey() {
		return new SDSIRSAPrivateKey(privateKey);
	}
}
