Java tutorial
/* * Copyright (c) 2010-2011, Martijn Brinkers, Djigzo. * * This file is part of Djigzo email encryption. * * Djigzo is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License * version 3, 19 November 2007 as published by the Free Software * Foundation. * * Djigzo is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Affero General Public License for more details. * * You should have received a copy of the GNU Affero General Public * License along with Djigzo. If not, see <http://www.gnu.org/licenses/> * * Additional permission under GNU AGPL version 3 section 7 * * If you modify this Program, or any covered work, by linking or * combining it with aspectjrt.jar, aspectjweaver.jar, tyrex-1.0.3.jar, * freemarker.jar, dom4j.jar, mx4j-jmx.jar, mx4j-tools.jar, * spice-classman-1.0.jar, spice-loggerstore-0.5.jar, spice-salt-0.8.jar, * spice-xmlpolicy-1.0.jar, saaj-api-1.3.jar, saaj-impl-1.3.jar, * wsdl4j-1.6.1.jar (or modified versions of these libraries), * containing parts covered by the terms of Eclipse Public License, * tyrex license, freemarker license, dom4j license, mx4j license, * Spice Software License, Common Development and Distribution License * (CDDL), Common Public License (CPL) the licensors of this Program grant * you additional permission to convey the resulting work. */ package mitm.common.security; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertTrue; import java.security.Key; import java.security.KeyFactory; import java.security.PrivateKey; import java.security.PublicKey; import java.security.spec.InvalidKeySpecException; import java.security.spec.KeySpec; import java.security.spec.PKCS8EncodedKeySpec; import java.security.spec.X509EncodedKeySpec; import javax.crypto.SecretKey; import javax.crypto.SecretKeyFactory; import javax.crypto.spec.PBEKeySpec; import mitm.common.security.KeyEncoder.KeyWasEncryptedKeyEncoderException; import mitm.common.security.crypto.Encryptor; import mitm.common.security.crypto.impl.PasswordBasedEncryptor; import mitm.common.util.MiscStringUtils; import org.apache.commons.codec.DecoderException; import org.apache.commons.codec.binary.Base64; import org.apache.commons.codec.binary.Hex; import org.apache.commons.lang.ArrayUtils; import org.apache.log4j.PropertyConfigurator; import org.junit.BeforeClass; import org.junit.Test; public class KeyEncoderTest { private final static String ENCODED_PRIVATE_KEY = "308204bf020100300d06092a864886f70d0101010500048204a9308204a5" + "0201000282010100b7c0b5ac2250390fe9da9b800bdb0a1b7f21614d1e7c" + "5db67438a9d1f793c0cf0403a3523981f17885e145dbc0e4c927a184c024" + "6e7a79ae29f7ad4e1a36db1db567c793547b96a8275e93d37ad17006ca51" + "6f3ed4bfbff9883e2a351d8c5c76a24502344e8711e76843b3ba05f7a551" + "5287dba46b05033c7756b531512034845fc7ae350ebc720ed83e7df7ebd8" + "ade16b0d961c15277fd5802b724c3d9392a7e99d2d06bf55b5d2516152b1" + "d9c249561e3887f075e2bebe8e331cdc3fe5de60af36285e514b14163b34" + "af15e6bb48e6b232366f05d73ad261714854833305ba06f1430d5b0c8383" + "7c49c9408c8e4d674b9a9494a6b0dc66e0b4d2107d78f26f020301000102" + "82010100a857d3d8bca2f47420d1d74e6b0e2467668425496ad9935d5982" + "a40a29a062af05c573761c1b7126f2b89cb0a43ab61329c59de68294902f" + "c0611994092e22764840a8b5d05b5d7df67b8e40dc2f4e4bda44daff1c18" + "03ffcf12ecc636a8e5f905d6e51b18aa63fbb628f85a3fa74efc7ef8da7f" + "fa4fe054201cfee90ca2cd98be5ab0de6f631ac574433573a05f797a6c67" + "f5f2ebac8abe4acb64ea926971ec6055cd3fffee636146199932f6868fbe" + "e39eab7e93c97c930bc8a92c75714459c74d0dc44d6a33660aec06735fa1" + "65d18b3511e28a225b513865c881ceb7b968379119a54e4f92c37abfb110" + "f760a0e3bc1b6d57141a20877dbd46819686f4f902818100e9188525d800" + "37f73d4f3d90a330911820228c29f80a3a63fddb09df82766d6cfdb46bdd" + "d163b780246edda6a4e2ec5c65453740e6cd191702afc2178b13123031ae" + "fd384383825d8fa60024f9b78d9c9ff1bf6f53e49528e1aba515a91f8066" + "54cd9488092a8f730133340dcc402d0b2cea149a3a6fdb1702f1890462a8" + "8f6d02818100c9cef9be785397ffbda7df90d7e6bc1d5a607950c4323114" + "9636e0b6c0a5ebc281fd0027463cc858fb94f8084baa0f93f1f33f18c40d" + "8a47666b7190efff38f869229b8e84eea8fcd559b2349873d96e187b9933" + "35ae63034ec926c341eaede9ac696c4b6029969fbeb8194c9f2b44e2c831" + "bb7c3a07c1dd5cadbf81f9deb3cb02818073e7e96d63f6d7dd6cf3161df1" + "c7989e727c3b4e333482cc6dd2991a36f9447849bf895387671a3bf1e1de" + "fd9a47ec58155351a24821fc33e0f61c81307a8f34bfbfcfd2466002571b" + "b2e3a77f34b28a0b4e5e6eb13c9c9ef37832628ef2471a9b588e5f068fcf" + "3cd47fed865ee61a7fd019a59cfb29dbbb998f191ec1202811028181008e" + "753c1937a992f7e632b5fff2589fdc7caaf3988f16fb4c94096331bee6a1" + "79a9f725ff93765edb69a52c3df6e3b2a1763f86fffd8dad5a5fb362f4b4" + "664f1a146568b7ffa0d5cbbcf3d7778752e85eee8b79870bd2f174294e97" + "bd682fe608793be6458339786985e14182b42d803032afe0b07dea71f0c8" + "76a264a7358d6702818100b2a67f02d933b860a2675f616a8f163eea3ef9" + "d23bc29416fe8b02582635a56b3278af0d98a4a8d7367c1bf21cf06841b8" + "f5e7f53e08062d90355aa90c4ff4e07d3eb2a5d356a5b4617e2ff114db1c" + "3c429ffaa552264a670b24b12b372558997b8f1fbd6df41efac697c5c9f3" + "2571eef344416eb642818b3886a16ec45381a3"; private final static String ENCODED_PUBLIC_KEY = "30820122300d06092a864886f70d01010105000382010f003082010a0282" + "010100b7c0b5ac2250390fe9da9b800bdb0a1b7f21614d1e7c5db67438a9" + "d1f793c0cf0403a3523981f17885e145dbc0e4c927a184c0246e7a79ae29" + "f7ad4e1a36db1db567c793547b96a8275e93d37ad17006ca516f3ed4bfbf" + "f9883e2a351d8c5c76a24502344e8711e76843b3ba05f7a5515287dba46b" + "05033c7756b531512034845fc7ae350ebc720ed83e7df7ebd8ade16b0d96" + "1c15277fd5802b724c3d9392a7e99d2d06bf55b5d2516152b1d9c249561e" + "3887f075e2bebe8e331cdc3fe5de60af36285e514b14163b34af15e6bb48" + "e6b232366f05d73ad261714854833305ba06f1430d5b0c83837c49c9408c" + "8e4d674b9a9494a6b0dc66e0b4d2107d78f26f0203010001"; private final static String BASE64_ENCODED_PUBLIC_KEY = "rO0ABXcEAAAAAXQAA1JTQXQABVguNTA5fnIAJ21pdG0uY29tbW9uLnNlY3VyaXR5LktleUVuY29k" + "ZXIkS2V5VHlwZQAAAAAAAAAAEgAAeHIADmphdmEubGFuZy5FbnVtAAAAAAAAAAASAAB4cHQABlBV" + "QkxJQ3cBAXVyAAJbQqzzF/gGCFTgAgAAeHAAAAFUlklfx6SWxIkAAAAQqlTT5UeRQPc+wjW7QyKz" + "/AAACAAAAAEwlrGiAHd1Z70QrtL6i5Y4bTEKTP6x5DVhG4uLtXBiv4Z2ixvCDlLbjEgGPzM+RTYs" + "c0mrNKGIVHYTQhyhJONdgUE/TbpU72K10EEo+73Y6zEvxg0gvzfhXf9c8jase0AesuWxvq8N52OJ" + "Cb6y95OSzc8PQau0+I7reqAsoFBSWc1CXGBAFZswNw60Z4zkYLQAflyQ/H18/7L/o83WVkiIj6mf" + "QWLP8ve3CfUbZHG6jQ8b666kQy50j1dJ8bS1EMVdco+YBCc7PHpDJ3uaghiDMLgy+ABagFMxYX9s" + "H56SgMU5ItIEzCVRFMfEE7VsfdlyGqHsJ+pTT2jvPQyvKtbrQnHzbn5GhwvNS1jxShWJvmzr7ANz" + "VTqU9JE2eHioRmDa/sX4i9kqSDMf6GbdKnLluA=="; private static SecurityFactory securityFactory; private static KeyFactory keyFactory; private static Encryptor encryptor; private static PublicKey publicKey; private static PrivateKey privateKey; @BeforeClass public static void setUpBeforeClass() throws Exception { PropertyConfigurator.configure("conf/log4j.properties"); securityFactory = SecurityFactoryFactory.getSecurityFactory(); keyFactory = securityFactory.createKeyFactory("RSA"); publicKey = decodePublicKey(ENCODED_PUBLIC_KEY); privateKey = decodePrivateKey(ENCODED_PRIVATE_KEY); encryptor = new PasswordBasedEncryptor("test"); } private static PrivateKey decodePrivateKey(String encoded) throws DecoderException, InvalidKeySpecException { byte[] rawKey = Hex.decodeHex(encoded.toCharArray()); KeySpec keySpec = new PKCS8EncodedKeySpec(rawKey); return keyFactory.generatePrivate(keySpec); } private static PublicKey decodePublicKey(String encoded) throws DecoderException, InvalidKeySpecException { byte[] rawKey = Hex.decodeHex(encoded.toCharArray()); KeySpec keySpec = new X509EncodedKeySpec(rawKey); return keyFactory.generatePublic(keySpec); } @Test public void testSerializePublicKey() throws Exception { byte[] serialized = KeyEncoder.encode(publicKey, encryptor); assertNotNull(serialized); Key key = KeyEncoder.decode(serialized, encryptor); assertEquals(publicKey, key); } @Test public void testSerializePublicKeyNoEncrypt() throws Exception { byte[] serialized = KeyEncoder.encode(publicKey); assertNotNull(serialized); Key key = KeyEncoder.decode(serialized); assertEquals(publicKey, key); } @Test(expected = KeyWasEncryptedKeyEncoderException.class) public void testDeserializeKeyMissingPassword() throws Exception { byte[] serialized = KeyEncoder.encode(publicKey, encryptor); assertNotNull(serialized); KeyEncoder.decode(serialized); } @Test public void testSerializePrivateKey() throws Exception { byte[] serialized = KeyEncoder.encode(privateKey, encryptor); assertNotNull(serialized); Key key = KeyEncoder.decode(serialized, encryptor); assertEquals(privateKey, key); } @Test public void testSerializeSecretKey() throws Exception { PBEKeySpec keySpec = new PBEKeySpec("test".toCharArray(), new byte[] { 1 }, 1); SecretKeyFactory secretKeyFactory = securityFactory .createSecretKeyFactory("PBEWITHSHA256AND128BITAES-CBC-BC"); Key secretKey = secretKeyFactory.generateSecret(keySpec); byte[] serialized = KeyEncoder.encode(secretKey, encryptor); assertNotNull(serialized); Key key = KeyEncoder.decode(serialized, encryptor); assertTrue(key instanceof SecretKey); assertTrue(ArrayUtils.isEquals(secretKey.getEncoded(), key.getEncoded())); } @Test public void testDeSerializePublicKey() throws Exception { Key key = KeyEncoder.decode(Base64.decodeBase64(MiscStringUtils.toAsciiBytes(BASE64_ENCODED_PUBLIC_KEY)), encryptor); assertTrue(key instanceof PublicKey); assertTrue(ArrayUtils.isEquals(publicKey.getEncoded(), key.getEncoded())); } }