/*
*
* Panbox - encryption for cloud storage
* Copyright (C) 2014-2015 by Fraunhofer SIT and Sirrix AG
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
* Additonally, third party code may be provided with notices and open source
* licenses from communities and third parties that govern the use of those
* portions, and any licenses granted hereunder do not alter any rights and
* obligations you may have under such open source licenses, however, the
* disclaimer of warranty and limitation of liability provisions of the GPLv3
* will apply to all the product.
*
*/
package org.panbox.core.keymgmt;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
import java.io.File;
import java.io.IOException;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.NoSuchAlgorithmException;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.SecureRandom;
import java.security.SignatureException;
import java.util.Collection;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.Map;
import javax.crypto.SecretKey;
import org.junit.After;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.TemporaryFolder;
import org.panbox.core.crypto.CryptCore;
import org.panbox.core.exception.SymmetricKeyEncryptionException;
public class TestAddUserToShare {
IVolume volume;
static PrivateKey aKey_sig;
static PublicKey aKey_sig_pub;
static PrivateKey aDevKey1_enc_priv;
static PublicKey aDevKey1_enc;
static PublicKey bKey_enc_pub;
Map<String, PublicKey> dkList;
@Rule
public TemporaryFolder folder = new TemporaryFolder();
private String dbName;
@BeforeClass
public static void setUpClass() {
try {
KeyPairGenerator gen = KeyPairGenerator.getInstance("RSA");
SecureRandom random = SecureRandom.getInstance("SHA1PRNG");
gen.initialize(1024, random);
KeyPair aPair = gen.generateKeyPair();
aKey_sig = aPair.getPrivate();
aKey_sig_pub = aPair.getPublic();
aPair = gen.generateKeyPair();
aDevKey1_enc_priv = aPair.getPrivate();
aDevKey1_enc = aPair.getPublic();
KeyPair bPair = gen.generateKeyPair();
bKey_enc_pub = bPair.getPublic();
} catch (NoSuchAlgorithmException e) {
fail(e.getMessage());
}
}
@Before
public void setUp() throws NoSuchMethodException, SecurityException,
InstantiationException, IllegalAccessException,
IllegalArgumentException, InvocationTargetException, IOException {
File newFolder = folder.newFolder(".metadata");
System.out.println("Create temporary folder: " + newFolder.mkdirs());
dbName = newFolder.getAbsolutePath();
File dbfile = new File(dbName + File.separator + Volume.DB_FILE);
if (dbfile.exists())
dbfile.delete();
// init ShareMetadata and SharePartList and sign the latter
volume = new Volume(dbName);
ShareMetaData shareMetaData = null;
try {
shareMetaData = new ShareMetaData(new JDBCHelperNonRevokeable(
"jdbc:sqlite:" + dbName + File.separator), aKey_sig_pub);
} catch (Exception e) {
fail(e.getMessage());
}
try {
Field smdField = Volume.class.getDeclaredField("shareMetaData");
smdField.setAccessible(true);
smdField.set(volume, shareMetaData);
} catch (Exception e) {
fail(e.getMessage());
}
try {
shareMetaData.initSharePartList().sign(aKey_sig);
} catch (SignatureException e2) {
fail(e2.getMessage());
}
dkList = new HashMap<String, PublicKey>();
dkList.put("Dev1", aDevKey1_enc);
try {
shareMetaData.createDeviceList(aKey_sig_pub, dkList).sign(aKey_sig);
} catch (SignatureException e2) {
fail(e2.getMessage());
}
SecretKey sk = CryptCore.generateSymmetricKey();
Collection<DeviceList> deviceLists = shareMetaData.getDeviceLists()
.values();
Collection<PublicKey> pubKeys = new LinkedList<PublicKey>();
for (DeviceList devList : deviceLists) {
pubKeys.addAll(devList.getPublicKeys());
}
// fetch ShareKeyDB
ShareKeyDB db = shareMetaData.getShareKeys();
try {
db.add(sk, pubKeys);
} catch (SymmetricKeyEncryptionException e1) {
fail(e1.getMessage());
}
}
@After
public void tearDown() {
volume = null;
File dbfile = new File(dbName + File.separator + Volume.DB_FILE);
if (dbfile.exists())
dbfile.delete();
}
@Test
public void test() {
// Precondition
// Volume/Share has been initialized as in TestInitVolume
// Owner A has a full KeySet
// Owner A has Public Keys of User B
assertNotNull(volume);
try {
// fetch Share MetaData
ShareMetaData shareMetaData = volume
.loadShareMetaData(aKey_sig_pub);
assertNotNull(shareMetaData);
// fetch SharekKeyDatabase
ShareKeyDB db = shareMetaData.getShareKeys();
assertNotNull(db);
// Receive the latest set of encrypted ShareKeys
ShareKeyDBEntry entry = db.getLastEntry();
// decrypt ShareKey using owners device key
SecretKey sk = CryptCore.decryptShareKey(entry, aDevKey1_enc,
aDevKey1_enc_priv);
assertNotNull(sk);
// receive SharePartList
SharePartList spl = shareMetaData.getSharePartList();
assertEquals("SharePartList is not empty, although it should be",
0, spl.size());
// Verify SharePartList
assertTrue(CryptCore.verifySignature(spl, spl.getSignature(),
aKey_sig_pub));
// Add User B's public master encryption key to SharePartList
spl.add(bKey_enc_pub, "USER_B");
assertEquals("SharePartList has not the expected size", 1,
spl.size());
// Sign new SharePartList
spl.sign(aKey_sig);
// Verify Signature
assertTrue(CryptCore.verifySignature(spl, spl.getSignature(),
aKey_sig_pub));
// Add Encrypted Sharekey for User B to ShareKeyDatabase
int before = entry.size();
entry.addEncryptedKey(sk, bKey_enc_pub);
assertEquals(before + 1, entry.size());
} catch (Exception e) {
fail(e.getMessage());
}
}
}