package com.kryptnostic.crypto.v1.keys;

import java.io.IOException;
import java.security.InvalidAlgorithmParameterException;
import java.security.InvalidKeyException;
import java.security.KeyPair;
import java.security.NoSuchAlgorithmException;
import java.security.SignatureException;
import java.security.spec.InvalidKeySpecException;
import java.security.spec.InvalidParameterSpecException;

import javax.crypto.BadPaddingException;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.NoSuchPaddingException;

import org.junit.Assert;
import org.junit.BeforeClass;
import org.junit.Test;

import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.kryptnostic.crypto.PrivateKey;
import com.kryptnostic.crypto.PublicKey;
import com.kryptnostic.crypto.v1.ciphers.Cypher;
import com.kryptnostic.crypto.v1.keys.Kodex.CorruptKodexException;
import com.kryptnostic.crypto.v1.keys.Kodex.SealedKodexException;
import com.kryptnostic.kodex.v1.serialization.jackson.KodexObjectMapperFactory;
import com.kryptnostic.users.v1.UserKey;

public class KodexTests {
    private static KeyPair                  pair;
    private static KodexMarshaller<UserKey> marshaller;
    private static PrivateKey               privateKey = new PrivateKey( 128, 64 );
    private static PublicKey                publicKey  = new PublicKey( privateKey );

    @BeforeClass
    public static void generateKeys() throws NoSuchAlgorithmException {
        pair = Keys.generateRsaKeyPair( 1024 );
        marshaller = new JacksonKodexMarshaller<UserKey>( UserKey.class );
    }

    @Test
    public void testSerializeDeserialize() throws InvalidKeyException, InvalidKeySpecException,
            NoSuchAlgorithmException, NoSuchPaddingException, IllegalBlockSizeException, BadPaddingException,
            InvalidParameterSpecException, SealedKodexException, IOException, InvalidAlgorithmParameterException,
            SignatureException, CorruptKodexException {
        Kodex<String> expected = new Kodex<String>(
                Cypher.RSA_OAEP_SHA1_1024,
                Cypher.AES_CTR_PKCS5_128,
                pair.getPublic() );
        Assert.assertTrue( expected.isSealed() );

        expected.unseal( pair.getPrivate() );
        Assert.assertTrue( !expected.isSealed() );

        expected.setKey( "test", marshaller, new UserKey( "kryptnostic", "tester" ) );
        expected.seal();

        Assert.assertTrue( expected.isSealed() );

        expected.unseal( pair.getPrivate() );
        Assert.assertTrue( !expected.isSealed() );

        expected.setKeyWithJackson( PrivateKey.class.getCanonicalName(), privateKey, PrivateKey.class );
        expected.setKeyWithJackson( PublicKey.class.getCanonicalName(), publicKey, PublicKey.class );

        ObjectMapper mapper = KodexObjectMapperFactory.getObjectMapper();

        String k = mapper.writeValueAsString( expected );
        Kodex<String> actual = mapper.readValue( k, new TypeReference<Kodex<String>>() {} );

        Assert.assertTrue( actual.isSealed() );
        actual.unseal( pair.getPrivate() );

        Assert.assertEquals( expected.getKey( "test", marshaller ), actual.getKey( "test", marshaller ) );
        Assert.assertEquals(
                privateKey,
                expected.getKeyWithJackson( PrivateKey.class.getCanonicalName(), PrivateKey.class ) );
        Assert.assertEquals(
                publicKey,
                expected.getKeyWithJackson( PublicKey.class.getCanonicalName(), PublicKey.class ) );
    }
}

@@ -702,24 +702,81 @@
 jectMapper;%0A
+import com.kryptnostic.crypto.EncryptedSearchPrivateKey;%0A
 import com.k
@@ -1108,16 +1108,89 @@
 actory;%0A
+import com.kryptnostic.linear.EnhancedBitMatrix.SingularMatrixException;%0A
 import c
@@ -1289,24 +1289,25 @@
             
+ 
 pair;%0A    pr
@@ -1343,16 +1343,17 @@
 UserKey%3E
+ 
  marshal
@@ -1393,32 +1393,33 @@
 y               
+ 
 privateKey = new
@@ -1478,32 +1478,33 @@
                 
+ 
 publicKey  = new
@@ -1528,16 +1528,72 @@
 teKey );
+%0A    private static EncryptedSearchPrivateKey searchKey;
 %0A%0A    @B
@@ -1664,32 +1664,57 @@
 gorithmException
+, SingularMatrixException
  %7B%0A        pair 
@@ -1744,24 +1744,80 @@
 ir( 1024 );%0A
+        searchKey = new EncryptedSearchPrivateKey( 8 );%0A
         mars
@@ -3062,16 +3062,198 @@
 class );
+%0A        expected.setKeyWithJackson(%0A                EncryptedSearchPrivateKey.class.getCanonicalName(),%0A                searchKey,%0A                EncryptedSearchPrivateKey.class );
 %0A%0A      
@@ -3985,21 +3985,447 @@
 y.class ) );
+%0A%0A        EncryptedSearchPrivateKey recoveredSearchKey = expected.getKeyWithJackson(%0A                EncryptedSearchPrivateKey.class.getCanonicalName(),%0A                EncryptedSearchPrivateKey.class );%0A%0A        Assert.assertEquals( searchKey.getLeftSquaringMatrix(), recoveredSearchKey.getLeftSquaringMatrix() );%0A        Assert.assertEquals( searchKey.getRightSquaringMatrix(), recoveredSearchKey.getRightSquaringMatrix() );
 %0A    %7D%0A%7D%0A

add some more stuff to kodex tests