package cryptofundamentals.tests;

import static org.junit.Assert.*;

import java.security.InvalidKeyException;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.NoSuchAlgorithmException;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.Signature;
import java.security.SignatureException;

import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.KeyGenerator;
import javax.crypto.NoSuchPaddingException;
import javax.crypto.SecretKey;

import org.junit.Test;

public class AsymmetricTests {

	@Test
	public void generateAnRsaKeyPair() throws Exception {
		KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("RSA");
		keyPairGenerator.initialize(2048);
		KeyPair keyPair = keyPairGenerator.generateKeyPair();
		
		assertEquals("RSA", keyPair.getPublic().getAlgorithm());
		assertTrue(keyPair.getPublic().getEncoded().length > 2048 / 8);
		assertTrue(keyPair.getPrivate().getEncoded().length > 2048 / 8);
	}
	
	@Test
	public void encryptASymmetricKey() throws Exception {
		KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("RSA");
		keyPairGenerator.initialize(2048);
		KeyPair keyPair = keyPairGenerator.generateKeyPair();

		PublicKey publicKey = keyPair.getPublic();
		PrivateKey privateKey = keyPair.getPrivate();
		
		KeyGenerator keyGenerator = KeyGenerator.getInstance("AES");
		keyGenerator.init(256);
		SecretKey key = keyGenerator.generateKey();
		
		byte[] encryptedKey = encryptWithRsa(publicKey, key);
		byte[] decryptedKey = decryptWithRsa(privateKey, encryptedKey);
		
		assertArrayEquals(key.getEncoded(), decryptedKey);
	}
	
	@Test
	public void signeAMessage() throws Exception {
		KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("RSA");
		keyPairGenerator.initialize(2048);
		KeyPair keyPair = keyPairGenerator.generateKeyPair();

		PublicKey publicKey = keyPair.getPublic();
		PrivateKey privateKey = keyPair.getPrivate();

		String message = "Alice knows Bob's secret.";
		byte[] messageBytes = message.getBytes();
		
		byte[] signatureBytes = signMessage(privateKey, messageBytes);
		boolean verified = verifySignature(publicKey, messageBytes, signatureBytes);
		
		assertTrue(verified);
	}

	private byte[] encryptWithRsa(PublicKey publicKey, SecretKey key)
			throws Exception {
		
		Cipher rsa = Cipher.getInstance("RSA/ECB/OAEPWithSHA-256AndMGF1Padding");
		rsa.init(Cipher.ENCRYPT_MODE, publicKey);
		byte[] encryptedKey = rsa.doFinal(key.getEncoded());
		return encryptedKey;
	}

	private byte[] decryptWithRsa(PrivateKey privateKey, byte[] encryptedKey)
			throws Exception {
		
		Cipher rsa = Cipher.getInstance("RSA/ECB/OAEPWithSHA-256AndMGF1Padding");
		rsa.init(Cipher.DECRYPT_MODE, privateKey);
		byte[] decryptedKey = rsa.doFinal(encryptedKey);
		return decryptedKey;
	}

	private byte[] signMessage(PrivateKey privateKey, byte[] messageBytes)
			throws Exception {
		
		Signature signature = Signature.getInstance("SHA256withRSA");
		signature.initSign(privateKey);
		signature.update(messageBytes);
		return signature.sign();
	}

	private boolean verifySignature(PublicKey publicKey, byte[] messageBytes,
			byte[] signatureBytes) throws Exception {
		
		Signature signature = Signature.getInstance("SHA256withRSA");
		signature.initVerify(publicKey);
		signature.update(messageBytes);
		return signature.verify(signatureBytes);
	}

}

@@ -717,163 +717,33 @@
 Pair
-Generator keyPairGenerator = KeyPairGenerator.getInstance(%22RSA%22);%0A%09%09keyPairGenerator.initialize(2048);%0A%09%09KeyPair keyPair = keyPairGenerator.generateKeyPair
+ keyPair = generateRsaKey
 ();%0A
@@ -1017,163 +1017,33 @@
 Pair
-Generator keyPairGenerator = KeyPairGenerator.getInstance(%22RSA%22);%0A%09%09keyPairGenerator.initialize(2048);%0A%09%09KeyPair keyPair = keyPairGenerator.generateKeyPair
+ keyPair = generateRsaKey
 ();%0A
@@ -1484,17 +1484,16 @@
 oid sign
-e
 AMessage
@@ -1527,163 +1527,33 @@
 Pair
-Generator keyPairGenerator = KeyPairGenerator.getInstance(%22RSA%22);%0A%09%09keyPairGenerator.initialize(2048);%0A%09%09KeyPair keyPair = keyPairGenerator.generateKeyPair
+ keyPair = generateRsaKey
 ();%0A
@@ -1913,24 +1913,111 @@
 ified);%0A%09%7D%0A%0A
+%09private KeyPair generateRsaKey() throws NoSuchAlgorithmException %7B%0A%09%09return null;%0A%09%7D%0A%0A
 %09private byt
@@ -2179,125 +2179,18 @@
 %0A%09%09r
-sa.init(Cipher.ENCRYPT_MODE, publicKey);%0A%09%09byte%5B%5D encryptedKey = rsa.doFinal(key.getEncoded());%0A%09%09return encryptedKey
+eturn null
 ;%0A%09%7D
@@ -2374,73 +2374,13 @@
 %0A%09%09r
-sa.init(Cipher.DECRYPT_MODE, privateKey);%0A%09%09byte%5B%5D decryptedKey =
+eturn
  rsa
@@ -2407,31 +2407,8 @@
 y);%0A
-%09%09return decryptedKey;%0A
 %09%7D%0A%0A
@@ -2572,76 +2572,8 @@
 %22);%0A
-%09%09signature.initSign(privateKey);%0A%09%09signature.update(messageBytes);%0A
 %09%09re
@@ -2714,32 +2714,32 @@
  Exception %7B%0A%09%09%0A
+
 %09%09Signature sign
@@ -2790,77 +2790,8 @@
 %22);%0A
-%09%09signature.initVerify(publicKey);%0A%09%09signature.update(messageBytes);%0A
 %09%09re

Prepare to demonstrate RSA with JCE.