/** * This method returns a EncryptedData structure with all the necessary information to allow * storage in database. Encryted data is stored in file system without defined file name. Returned * data must be treated in this way: * * <ul> * <li>key must be stored NOWHERE, only must exist in the shared URL * <li>id, encryptedPath and encryptedName must be stored in database * </ul> * * With this data this methods builds a NEW KEY based on seed and applying the provided key. KEY * is the provided key and must be regenerated in each method invocation (one-time use). ID is the * encrypted seed, using the generated NEW KEY and an initialization vector based on seed itself, * built by #getIv(String). PATH and NAME is encrypted with the same IV and NEW KEY as the ID. * With this protocol we are trying to avoid the possibility of recovering encrypted data because * the original key is never stored, only the owner of the shared URL has such key. So if the * server is compromised by an attacker, this one could not discover the path of a file associated * to a database record or decrypt a file content (because the lack of keys). * * @param content conted to be encrypted * @param name file name * @param seed value used to genererate the AES Initialization Vector * @param key AES key used for encryption * @return struct with reference info of encryptation result * @throws IOException * @throws FileNotFoundException */ protected EncryptedData doEncryptContent( InputStream content, String name, String seed, byte[] key) throws IOException, FileNotFoundException { byte[] iv = getIv(seed); byte[] encryptedIv = cryptoHelper.encryptIv(iv, key); byte[] newKey = Arrays.copyOf( encryptedIv, CryptoHelper.KEY_LENGTH / 8); // only first key size bytes (from a 16 bytes iv, the encrypted data is // 128+128, being last 128 padding data InputStream encryptedStream = cryptoHelper.encrypt(content, iv, newKey); String targetDirPath = getTargetDirPath(); File targetFile = getTargetFile(targetDirPath); FileOutputStream fos = new FileOutputStream(targetFile); IOUtils.copyLarge(encryptedStream, fos, new byte[512]); byte[] id = encryptString(seed, iv, newKey); byte[] encryptedPath = encryptString(targetFile.getPath(), iv, newKey); byte[] encryptedName = encryptString(name, iv, newKey); EncryptedData ed = new EncryptedData(); ed.setKey(key); ed.setId(id); ed.setEncryptedPath(encryptedPath); ed.setEncryptedName(encryptedName); return ed; }
protected byte[] encryptString(String s, byte[] iv, byte[] key) throws IOException, UnsupportedEncodingException { InputStream encryptedStream = cryptoHelper.encrypt(new ByteArrayInputStream(s.getBytes("utf-8")), iv, key); return IOUtils.toByteArray(encryptedStream); }