@Override public void inviteUser( String ownerAlias, PrivateKey ownerPrivSigKey, PublicKey ownerPubEncKey, PrivateKey ownerPrivEncKey, String alias, PublicKey userPubEncKey, PublicKey userPubSigKey) throws ShareMetaDataException { // Check if called by owner if (!Utils.keysMatch(shareMetaData.ownerPubSigKey, ownerPrivSigKey)) { throw new ShareMetaDataException("This method can only be called by the share owner!"); } SharePartList spl = shareMetaData.getSharePartList(); // Check if user alias already exists if (spl.getPublicKey(alias) == null) { spl.add(userPubSigKey, alias); } // Create deviceList and sign for user HashMap<String, PublicKey> dkList = new HashMap<String, PublicKey>(); dkList.put(IVolume.MASTER_KEY, userPubEncKey); DeviceList devices = shareMetaData.createDeviceList(userPubSigKey, dkList); try { shareMetaData.addObfuscationKey(ownerPubEncKey, ownerPrivEncKey, userPubEncKey); } catch (SymmetricKeyEncryptionException | SymmetricKeyDecryptionException e) { throw new ShareMetaDataException("Could not add encrypted obfuscation key for new user", e); } // add encrypted sharekey for device try { this.shareMetaData.shareKeys.addDevice(ownerPubEncKey, ownerPrivEncKey, userPubEncKey); } catch (Exception e) { throw new ShareMetaDataException("Could not add encrypted share keys for new user", e); } // Sign everything try { spl.sign(ownerPrivSigKey); } catch (SignatureException e) { throw new ShareMetaDataException("Could not add new user to ShareParticipantList.", e); } try { devices.sign(ownerPrivSigKey, shareMetaData.shareKeys, shareMetaData.obfuscationKeys); } catch (SignatureException e) { throw new ShareMetaDataException("Could not sign devicelist", e); } this.shareMetaData.persist(); this.shareMetaData.persist(devices); }
private synchronized void createIVFile(byte[] iv, String encryptedName, SecretKey key) throws ObfuscationException { // store IV in pool String ivhex = Utils.bytesToHex(iv); byte[] lookupHashBytes = createLookupHash(encryptedName, key); String lookupHashStr = Utils.bytesToHex(lookupHashBytes); char firstChar = lookupHashStr.toUpperCase().charAt(0); File dirs = getIVPoolSubDir(firstChar); // java based file creation File ivFile = new File(dirs.getAbsolutePath() + File.separator + lookupHashStr + ivhex); try { ivFile.createNewFile(); } catch (IOException e) { logger.error("Unable to create IV sidecar file!", e); throw new ObfuscationException("Unable to create IV sidecar file!", e); } }
@Override public void addDevice( String alias, PublicKey masterPubSigKey, PrivateKey masterPrivSigKey, String newDeviceAlias, PublicKey newDevicePubKey, PublicKey masterPubEncKey, PrivateKey masterPrivEncKey) throws ShareMetaDataException { if (IVolume.MASTER_KEY.equals(newDeviceAlias)) { throw new IllegalArgumentException("Illegal alias for device. Choose another alias"); } // verify matching public/private keys if (!Utils.keysMatch(masterPubSigKey, masterPrivSigKey)) { throw new IllegalArgumentException( "User's master private and public signature keys do not match!"); } if (!Utils.keysMatch(masterPubEncKey, masterPrivEncKey)) { throw new IllegalArgumentException( "User's master private and public encryption keys do not match!"); } // verify integrity of ShareParticipantList SharePartList sharePartList = shareMetaData.getSharePartList(); try { SignatureHelper.verify( sharePartList, sharePartList.getSignature(), shareMetaData.ownerPubSigKey); } catch (InvalidKeyException | NoSuchAlgorithmException | SignatureException | SerializationException e) { throw new ShareMetaDataException("Could not verify ShareParticipantsList signature", e); } // check if masterPubSigKey is in ShareParticipants if (!sharePartList.getPublicKey(alias).equals(masterPubSigKey)) { throw new ShareMetaDataException( "Given user singature publickey is not " + "in sharepartiticapnts list"); } // Get DeviceList for user DeviceList deviceList = shareMetaData.getDeviceLists().get(masterPubSigKey); if (deviceList == null) { throw new ShareMetaDataException( "DeviceList for user " + alias + " was empty, which should never be the case."); } // add device deviceList.addDevice(newDeviceAlias, newDevicePubKey); // add encrypted Obfuscation key for new device try { shareMetaData.addObfuscationKey(masterPubEncKey, masterPrivEncKey, newDevicePubKey); } catch (SymmetricKeyEncryptionException | SymmetricKeyDecryptionException e) { throw new ShareMetaDataException("Could not add encrypted obfuscation key for new device", e); } // add encrypted sharekey for device try { this.shareMetaData.shareKeys.addDevice(masterPubEncKey, masterPrivEncKey, newDevicePubKey); } catch (Exception e) { throw new ShareMetaDataException("Could not add encrypted share keys for new device", e); } // Sign everything try { deviceList.sign(masterPrivSigKey, shareMetaData.shareKeys, shareMetaData.obfuscationKeys); } catch (SignatureException e) { throw new ShareMetaDataException("Could not sign devicelist", e); } this.shareMetaData.persist(deviceList); }
@Override public ShareMetaData createShareMetaData( String ownerAlias, PublicKey ownerPubSigKey, PrivateKey ownerPrivSigKey, PublicKey ownerPubEncKey, PrivateKey ownerPrivEncKey, String deviceAlias, PublicKey devicePubKey) throws IllegalArgumentException, ShareMetaDataException { if (IVolume.MASTER_KEY.equals(deviceAlias)) { throw new IllegalArgumentException("Illegal alias for device. Choose another alias"); } if (db.exists()) { throw new IllegalArgumentException( "Can't initialize new share metadata, because database already exists."); } // verify matching public/private keys if (!Utils.keysMatch(ownerPubSigKey, ownerPrivSigKey)) { throw new IllegalArgumentException("Owners master private and public key do not match!"); } shareMetaData = new ShareMetaData(db, ownerPubSigKey); try { this.shareMetaData.load(); } catch (InitializaionException e) { throw new ShareMetaDataException("Could not initialize ShareMetaData", e); } catch (SignatureException e) { throw new ShareMetaDataException("Could not verify signature", e); } catch (DeviceListException e) { throw new ShareMetaDataException("Could not verify signature", e); } // Init Participants list SharePartList spl = shareMetaData.initSharePartList(); spl.add(ownerPubSigKey, ownerAlias); // Init DeviceList HashMap<String, PublicKey> dkList = new HashMap<String, PublicKey>(); dkList.put(IVolume.MASTER_KEY, ownerPubEncKey); dkList.put(deviceAlias, devicePubKey); DeviceList devices = shareMetaData.createDeviceList(ownerPubSigKey, dkList); // Create ObfuscationKey try { shareMetaData.addObfuscationKey(ownerPubEncKey, null, null); shareMetaData.addObfuscationKey(ownerPubEncKey, ownerPrivEncKey, devicePubKey); } catch (SymmetricKeyEncryptionException | SymmetricKeyDecryptionException e) { throw new ShareMetaDataException("Could not initialize obfuscation key", e); } // Create initial ShareKey ShareKeyDB shareKeys = shareMetaData.getShareKeys(); SecretKey shareKey = CryptCore.generateSymmetricKey(); try { shareKeys.add(shareKey, dkList.values()); } catch (SymmetricKeyEncryptionException e1) { throw new ShareMetaDataException("Could not encrypt sharekey for device", e1); } try { spl.sign(ownerPrivSigKey); } catch (SignatureException e2) { throw new ShareMetaDataException("Could not sign SharePartList", e2); } try { devices.sign(ownerPrivSigKey, shareKeys, shareMetaData.obfuscationKeys); } catch (SignatureException e2) { throw new ShareMetaDataException("Could not sign DeviceList", e2); } shareMetaData.persist(); shareMetaData.persist(devices); return shareMetaData; }
/** * Deobfuscates a string with the given key and encodes it with Base64 * * @param str - string to deobfuscate * @param key - symmetric key used to decrypt the string * @return - deobfuscated string * @throws MissingIVException if for a given filename, no IV sidecar file could be found. * base64LookupHash will be set in this exception * @throws ObfuscationException */ public synchronized String deObfuscate(String str, SecretKey key) throws MissingIVException, ObfuscationException { logger.debug("Obfuscator(" + this.shareName + ") DeObfuscate(String, key): " + str); // lookup in cache if (cachedDeObfuscatedNames.containsKey(str)) { logger.debug("DeObfuscate(String, key) - return cached value for: " + str); return cachedDeObfuscatedNames.get(str); } // if not in cache, do processing byte[] lookupHash = createLookupHash(str, key); String sLookupHash = Utils.bytesToHex(lookupHash); byte[] iv = ivPoolImpl.getCachedIV(sLookupHash, this.shareName); if (null == iv) { // re-read IVs from file-system or server logger.debug("Obfuscator: RE-fetch IV Pool"); ivPoolImpl.fetchIVPool(this.sharePath, this.shareName); iv = ivPoolImpl.getCachedIV(sLookupHash, this.shareName); // // "direct" IV lookup // char firstChar = base64LookupHash.toUpperCase().charAt(0); // File path = getIVPoolSubDir(firstChar); // File[] res = path.listFiles((FileFilter) new PrefixFileFilter( // base64LookupHash)); // iv = Utils.hexToBytes(res[0].getName().substring(41)); } if (iv == null) { // this may be due to the CSP trying to resolve a conflict by // renaming two conflicting copies of a file. in this case, the // obfuscator's filename conflict resolution handler need to be // called to try to recover this situation. however, this needs to // be done *outside* of this method as we need full context (i.e. // absolute filename etc) // error cannot decode logger.error( "Could not find IV for hash: " + sLookupHash + " generated from obfuscate file: " + str); throw new MissingIVException( "Could not find IV for hash: " + sLookupHash + " generated from obfuscate file: " + str, sLookupHash); } String originalName = null; try { originalName = decryptFileName(str, key.getEncoded(), iv, false, EncodingType.BASE64); } catch (InvalidKeyException | NoSuchAlgorithmException | NoSuchPaddingException | InvalidAlgorithmParameterException | IllegalBlockSizeException | BadPaddingException | DataFormatException | IOException e) { logger.error("Could not deobfuscate string: " + str, e); throw new ObfuscationException("Could not decrypt string: " + str, e); } // do caching cachedDeObfuscatedNames.put(str, originalName); logger.debug( "Obfuscator(" + this.shareName + ") DeObfuscate(String, key)-return: " + originalName); return originalName; }