/** * Split the password property into file password and user password if necessary, and convert them * to the internal hash format. */ private void convertPasswords() { char[] password = removePassword(); boolean passwordHash = removeProperty("PASSWORD_HASH", false); // 如果PASSWORD_HASH参数是true那么不再进行SHA256 // 如果配置了CIPHER,则password包含两部份,用一个空格分开这两部份,第一部份是filePassword,第二部份是userPassword。 // 如果PASSWORD_HASH参数是true那么不再进行SHA256,此时必须使用16进制字符,字符个数是偶数。 // 如果PASSWORD_HASH参数是false,不必是16进制字符,会按SHA256算法进行hash if (getProperty("CIPHER", null) != null) { // split password into (filePassword+' '+userPassword) int space = -1; for (int i = 0, len = password.length; i < len; i++) { if (password[i] == ' ') { space = i; break; } } if (space < 0) { throw DbException.get(ErrorCode.WRONG_PASSWORD_FORMAT); } char[] np = new char[password.length - space - 1]; char[] filePassword = new char[space]; System.arraycopy(password, space + 1, np, 0, np.length); System.arraycopy(password, 0, filePassword, 0, space); Arrays.fill(password, (char) 0); password = np; // filePasswordHash用"file"进行hash fileEncryptionKey = FilePathEncrypt.getPasswordBytes(filePassword); filePasswordHash = hashPassword(passwordHash, "file", filePassword); } // userPasswordHash用用户名进行hash userPasswordHash = hashPassword(passwordHash, user, password); }
/** * Try to open the file. * * @param fileName the file name * @param readOnly whether the file should only be opened in read-only mode, even if the file is * writable * @param encryptionKey the encryption key, or null if encryption is not used */ public void open(String fileName, boolean readOnly, char[] encryptionKey) { if (file != null) { return; } if (fileName != null) { FilePath p = FilePath.get(fileName); // if no explicit scheme was specified, NIO is used if (p instanceof FilePathDisk && !fileName.startsWith(p.getScheme() + ":")) { // ensure the NIO file system is registered FilePathNio.class.getName(); fileName = "nio:" + fileName; } } this.fileName = fileName; FilePath f = FilePath.get(fileName); FilePath parent = f.getParent(); if (parent != null && !parent.exists()) { throw DataUtils.newIllegalArgumentException("Directory does not exist: {0}", parent); } if (f.exists() && !f.canWrite()) { readOnly = true; } this.readOnly = readOnly; try { file = f.open(readOnly ? "r" : "rw"); if (encryptionKey != null) { byte[] key = FilePathEncrypt.getPasswordBytes(encryptionKey); encryptedFile = file; file = new FilePathEncrypt.FileEncrypt(fileName, key, file); } file = FilePathCache.wrap(file); try { if (readOnly) { fileLock = file.tryLock(0, Long.MAX_VALUE, true); } else { fileLock = file.tryLock(); } } catch (OverlappingFileLockException e) { throw DataUtils.newIllegalStateException( DataUtils.ERROR_FILE_LOCKED, "The file is locked: {0}", fileName, e); } if (fileLock == null) { throw DataUtils.newIllegalStateException( DataUtils.ERROR_FILE_LOCKED, "The file is locked: {0}", fileName); } fileSize = file.size(); } catch (IOException e) { throw DataUtils.newIllegalStateException( DataUtils.ERROR_READING_FAILED, "Could not open file {0}", fileName, e); } }