diff --git a/core/java/algorithm/build.gradle b/core/java/algorithm/build.gradle
index 857d711b..7d2a00fa 100644
--- a/core/java/algorithm/build.gradle
+++ b/core/java/algorithm/build.gradle
@@ -1,5 +1,6 @@
plugins {
id 'java'
+ id 'c'
}
description = 'Master Password Algorithm Implementation'
@@ -9,8 +10,69 @@ dependencies {
exclude( module: 'joda-time' )
}
- compile 'com.github.joshjdevl.libsodiumjni:libsodium-jni:1.0.6'
compile 'com.fasterxml.jackson.core:jackson-annotations:2.9.5'
compile group: 'org.jetbrains', name: 'annotations', version: '13.0'
compile group: 'com.google.code.findbugs', name: 'jsr305', version: '3.0.1'
}
+
+processResources {
+ dependsOn 'mpwSharedLibrary'
+}
+
+// TODO: nativeGenHeaders should run prior to mpwSharedLibrary
+// TODO: but that creates a cyclic dependency since processResources runs before compileJava which nativeGenHeaders depends on.
+//task mpwSharedLibrary {
+// dependsOn processResources
+//}
+build {
+// dependsOn 'mpwSharedLibrary'
+ dependsOn 'nativeGenHeaders'
+}
+
+task nativeGenHeaders {
+ description "Uses javah to regenerate the JNI header files"
+ inputs.file sourceSets.main.output.asFileTree.matching {
+ include 'com/lyndir/masterpassword/impl/MPAlgorithmV0.class'
+ }
+ outputs.file 'src/mpw/c/jni_mpw.h'
+ def classpath = files( sourceSets.main.compileClasspath, sourceSets.main.output )
+ doLast {
+ ant.javah( class: 'com.lyndir.masterpassword.impl.MPAlgorithmV0',
+ outputFile: 'src/mpw/c/jni_mpw.h',
+ classpath: classpath.asPath )
+ }
+}
+
+model {
+ components {
+ mpw( NativeLibrarySpec ) {
+ binaries.all {
+ if (targetPlatform.operatingSystem.macOsX) {
+ cCompiler.args '-I', "${org.gradle.internal.jvm.Jvm.current().javaHome}/include"
+ cCompiler.args '-I', "${org.gradle.internal.jvm.Jvm.current().javaHome}/include/darwin"
+ cCompiler.args '-mmacosx-version-min=10.4'
+ linker.args '-mmacosx-version-min=10.4'
+ } else if (targetPlatform.operatingSystem.linux) {
+ cCompiler.args '-I', "${org.gradle.internal.jvm.Jvm.current().javaHome}/include"
+ cCompiler.args '-I', "${org.gradle.internal.jvm.Jvm.current().javaHome}/include/linux"
+ cCompiler.args '-D_FILE_OFFSET_BITS=64'
+ } else if (targetPlatform.operatingSystem.windows) {
+ cCompiler.args "-I${org.gradle.internal.jvm.Jvm.current().javaHome}/include"
+ cCompiler.args "-I${org.gradle.internal.jvm.Jvm.current().javaHome}/include/win32"
+ linker.args "Shlwapi.lib", "Advapi32.lib"
+ } else if (targetPlatform.operatingSystem.freeBSD) {
+ cCompiler.args '-I', "${org.gradle.internal.jvm.Jvm.current().javaHome}/include"
+ cCompiler.args '-I', "${org.gradle.internal.jvm.Jvm.current().javaHome}/include/freebsd"
+ }
+ }
+ // TODO: Can't we add the sharedLibraryFile to the resources through some kind of task dependency instead?
+ binaries.withType( SharedLibraryBinarySpec ) {
+ sourceSets.main.resources.srcDirs it.sharedLibraryFile.parent
+// copy {
+// from sharedLibraryFile
+// to sourceSets.main.resources.outputDir
+// }
+ }
+ }
+ }
+}
diff --git a/core/java/algorithm/src/main/java/com/lyndir/masterpassword/impl/MPAlgorithmV0.java b/core/java/algorithm/src/main/java/com/lyndir/masterpassword/impl/MPAlgorithmV0.java
index 2bbac74b..75cf15e4 100644
--- a/core/java/algorithm/src/main/java/com/lyndir/masterpassword/impl/MPAlgorithmV0.java
+++ b/core/java/algorithm/src/main/java/com/lyndir/masterpassword/impl/MPAlgorithmV0.java
@@ -27,7 +27,6 @@ import com.google.common.primitives.Bytes;
import com.google.common.primitives.UnsignedInteger;
import com.lyndir.lhunath.opal.system.*;
import com.lyndir.lhunath.opal.system.logging.Logger;
-import com.lyndir.lhunath.opal.system.util.ConversionUtils;
import com.lyndir.masterpassword.*;
import java.nio.*;
import java.nio.charset.Charset;
@@ -38,7 +37,6 @@ import javax.annotation.Nullable;
import javax.crypto.*;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
-import org.libsodium.jni.Sodium;
/**
@@ -53,8 +51,7 @@ public class MPAlgorithmV0 extends MPAlgorithm {
protected static final int AES_BLOCKSIZE = 128 /* bit */;
static {
- if (Sodium.sodium_init() < 0)
- throw new IllegalStateException( "Couldn't initialize libsodium." );
+ Native.load( MPAlgorithmV0.class, "mpw" );
}
public final Version version = MPAlgorithm.Version.V0;
@@ -93,7 +90,7 @@ public class MPAlgorithmV0 extends MPAlgorithm {
@Nullable
protected byte[] scrypt(final byte[] secret, final byte[] salt, final int keySize) {
byte[] buffer = new byte[keySize];
- if (Sodium.crypto_pwhash_scryptsalsa208sha256_ll(
+ if (_scrypt(
secret, secret.length, salt, salt.length,
scrypt_N(), scrypt_r(), scrypt_p(), buffer, buffer.length ) < 0)
return null;
@@ -101,6 +98,8 @@ public class MPAlgorithmV0 extends MPAlgorithm {
return buffer;
}
+ protected native int _scrypt(byte[] passwd, int passwdlen, byte[] salt, int saltlen, int N, int r, int p, byte[] buf, int buflen);
+
@Override
public byte[] siteKey(final byte[] masterKey, final String siteName, UnsignedInteger siteCounter,
final MPKeyPurpose keyPurpose, @Nullable final String keyContext) {
@@ -259,27 +258,29 @@ public class MPAlgorithmV0 extends MPAlgorithm {
public String siteResultFromDerive(final byte[] masterKey, final byte[] siteKey,
final MPResultType resultType, @Nullable final String resultParam) {
- if (resultType == MPResultType.DeriveKey) {
- int resultParamInt = ConversionUtils.toIntegerNN( resultParam );
- if (resultParamInt == 0)
- resultParamInt = mpw_keySize_max();
- if ((resultParamInt < mpw_keySize_min()) || (resultParamInt > mpw_keySize_max()) || ((resultParamInt % 8) != 0))
- throw logger.bug( "Parameter is not a valid key size (should be 128 - 512): %s", resultParam );
- int keySize = resultParamInt / 8;
- logger.trc( "keySize: %d", keySize );
+ throw new UnsupportedOperationException( "TODO" );
- // Derive key
- byte[] resultKey = null; // TODO: mpw_kdf_blake2b()( keySize, siteKey, MPSiteKeySize, NULL, 0, 0, NULL );
- if (resultKey == null)
- throw logger.bug( "Could not derive result key." );
-
- // Base64-encode
- String b64Key = Preconditions.checkNotNull( BaseEncoding.base64().encode( resultKey ) );
- logger.trc( "b64 encoded -> key: %s", b64Key );
-
- return b64Key;
- } else
- throw logger.bug( "Unsupported derived password type: %s", resultType );
+ // if (resultType == MPResultType.DeriveKey) {
+ // int resultParamInt = ConversionUtils.toIntegerNN( resultParam );
+ // if (resultParamInt == 0)
+ // resultParamInt = mpw_keySize_max();
+ // if ((resultParamInt < mpw_keySize_min()) || (resultParamInt > mpw_keySize_max()) || ((resultParamInt % 8) != 0))
+ // throw logger.bug( "Parameter is not a valid key size (should be 128 - 512): %s", resultParam );
+ // int keySize = resultParamInt / 8;
+ // logger.trc( "keySize: %d", keySize );
+ //
+ // // Derive key
+ // byte[] resultKey = null; // TODO: mpw_kdf_blake2b()( keySize, siteKey, MPSiteKeySize, NULL, 0, 0, NULL );
+ // if (resultKey == null)
+ // throw logger.bug( "Could not derive result key." );
+ //
+ // // Base64-encode
+ // String b64Key = Preconditions.checkNotNull( BaseEncoding.base64().encode( resultKey ) );
+ // logger.trc( "b64 encoded -> key: %s", b64Key );
+ //
+ // return b64Key;
+ // } else
+ // throw logger.bug( "Unsupported derived password type: %s", resultType );
}
@Override
diff --git a/core/java/algorithm/src/main/java/com/lyndir/masterpassword/impl/Native.java b/core/java/algorithm/src/main/java/com/lyndir/masterpassword/impl/Native.java
new file mode 100644
index 00000000..9852ea48
--- /dev/null
+++ b/core/java/algorithm/src/main/java/com/lyndir/masterpassword/impl/Native.java
@@ -0,0 +1,59 @@
+//==============================================================================
+// This file is part of Master Password.
+// Copyright (c) 2011-2017, Maarten Billemont.
+//
+// Master Password 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.
+//
+// Master Password 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 can find a copy of the GNU General Public License in the
+// LICENSE file. Alternatively, see .
+//==============================================================================
+
+package com.lyndir.masterpassword.impl;
+
+import com.google.common.io.ByteStreams;
+import com.lyndir.lhunath.opal.system.logging.Logger;
+import java.io.*;
+
+
+/**
+ * @author lhunath, 2018-05-22
+ */
+public final class Native {
+ private static final Logger logger = Logger.get( Native.class );
+
+ private static final char FILE_DOT = '.';
+ private static final String NATIVES_PATH = "";
+
+ @SuppressWarnings({ "HardcodedFileSeparator", "LoadLibraryWithNonConstantString" })
+ public static void load(final Class> context, final String name) {
+ try {
+ String library = System.mapLibraryName( name );
+ int libraryDot = library.lastIndexOf( FILE_DOT );
+ String libraryName = (libraryDot > 0)? library.substring( 0, libraryDot ): library;
+ String libraryExtension = (libraryDot > 0)? library.substring( libraryDot ): "lib";
+ String libraryResource = String.format( "%s/%s", NATIVES_PATH, library );
+ InputStream libraryStream = context.getResourceAsStream( libraryResource );
+ if (libraryStream == null)
+ throw new IllegalStateException(
+ "Library: " + name + " (" + libraryResource + "), not found in class loader for: " + context );
+
+ File libraryFile = File.createTempFile( "libmpw", ".dylib" );
+ ByteStreams.copy( libraryStream, new FileOutputStream( libraryFile ) );
+ System.load( libraryFile.getAbsolutePath() );
+ libraryFile.deleteOnExit();
+ if (!libraryFile.delete())
+ logger.wrn( "Couldn't clean up library after loading: " + libraryFile );
+ }
+ catch (final IOException e) {
+ throw new IllegalStateException( "Couldn't load library: " + name, e );
+ }
+ }
+}
diff --git a/core/java/algorithm/src/mpw/c/jni_mpw.c b/core/java/algorithm/src/mpw/c/jni_mpw.c
new file mode 100644
index 00000000..c4532d7c
--- /dev/null
+++ b/core/java/algorithm/src/mpw/c/jni_mpw.c
@@ -0,0 +1,8 @@
+#include "jni_mpw.h"
+
+/** native int _scrypt(byte[] passwd, int passwdlen, byte[] salt, int saltlen, int N, int r, int p, byte[] buf, int buflen); */
+JNIEXPORT jint JNICALL Java_com_lyndir_masterpassword_impl_MPAlgorithmV0__1scrypt(JNIEnv *env, jobject obj,
+ jbyteArray passwd, jint passwdlen, jbyteArray salt, jint saltlen, jint N, jint r, jint p, jbyteArray buf, jint buflen) {
+
+ return -2;
+}
diff --git a/core/java/algorithm/src/mpw/c/jni_mpw.h b/core/java/algorithm/src/mpw/c/jni_mpw.h
new file mode 100644
index 00000000..990e3440
--- /dev/null
+++ b/core/java/algorithm/src/mpw/c/jni_mpw.h
@@ -0,0 +1,23 @@
+/* DO NOT EDIT THIS FILE - it is machine generated */
+#include
+/* Header for class com_lyndir_masterpassword_impl_MPAlgorithmV0 */
+
+#ifndef _Included_com_lyndir_masterpassword_impl_MPAlgorithmV0
+#define _Included_com_lyndir_masterpassword_impl_MPAlgorithmV0
+#ifdef __cplusplus
+extern "C" {
+#endif
+#undef com_lyndir_masterpassword_impl_MPAlgorithmV0_AES_BLOCKSIZE
+#define com_lyndir_masterpassword_impl_MPAlgorithmV0_AES_BLOCKSIZE 128L
+/*
+ * Class: com_lyndir_masterpassword_impl_MPAlgorithmV0
+ * Method: _scrypt
+ * Signature: ([BI[BIIII[BI)I
+ */
+JNIEXPORT jint JNICALL Java_com_lyndir_masterpassword_impl_MPAlgorithmV0__1scrypt
+ (JNIEnv *, jobject, jbyteArray, jint, jbyteArray, jint, jint, jint, jint, jbyteArray, jint);
+
+#ifdef __cplusplus
+}
+#endif
+#endif
diff --git a/core/java/tests/build.gradle b/core/java/tests/build.gradle
index b4033b02..56242948 100644
--- a/core/java/tests/build.gradle
+++ b/core/java/tests/build.gradle
@@ -11,4 +11,7 @@ dependencies {
testCompile group: 'org.testng', name: 'testng', version: '6.8.5'
testCompile group: 'ch.qos.logback', name: 'logback-classic', version: '1.1.2'
}
+//tasks.withType(Test) {
+// systemProperty "java.library.path", "/Users/lhunath/Documents/workspace/lyndir/MasterPassword/core/java/algorithm/build/libs/mpw/shared"
+//}
test.useTestNG()
diff --git a/platform-darwin/MasterPassword-JNI/MasterPassword-JNI.xcodeproj/project.pbxproj b/platform-darwin/MasterPassword-JNI/MasterPassword-JNI.xcodeproj/project.pbxproj
new file mode 100644
index 00000000..9ade388c
--- /dev/null
+++ b/platform-darwin/MasterPassword-JNI/MasterPassword-JNI.xcodeproj/project.pbxproj
@@ -0,0 +1,181 @@
+// !$*UTF8*$!
+{
+ archiveVersion = 1;
+ classes = {
+ };
+ objectVersion = 50;
+ objects = {
+
+/* Begin PBXFileReference section */
+ DA1554DE20B3928E00EA92C5 /* aes.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = aes.c; sourceTree = ""; };
+ DA1554DF20B3928E00EA92C5 /* mpw-algorithm.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "mpw-algorithm.h"; sourceTree = ""; };
+ DA1554E020B3928E00EA92C5 /* base64.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = base64.h; sourceTree = ""; };
+ DA1554E120B3928E00EA92C5 /* mpw-marshal.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = "mpw-marshal.c"; sourceTree = ""; };
+ DA1554E220B3928E00EA92C5 /* mpw-algorithm_v2.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = "mpw-algorithm_v2.c"; sourceTree = ""; };
+ DA1554E320B3928E00EA92C5 /* mpw-types.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = "mpw-types.c"; sourceTree = ""; };
+ DA1554E420B3928E00EA92C5 /* mpw-marshal-util.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = "mpw-marshal-util.c"; sourceTree = ""; };
+ DA1554E520B3928E00EA92C5 /* mpw-util.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = "mpw-util.c"; sourceTree = ""; };
+ DA1554E620B3928E00EA92C5 /* mpw-algorithm_v1.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = "mpw-algorithm_v1.c"; sourceTree = ""; };
+ DA1554E720B3928E00EA92C5 /* aes.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = aes.h; sourceTree = ""; };
+ DA1554E820B3928E00EA92C5 /* mpw-marshal.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "mpw-marshal.h"; sourceTree = ""; };
+ DA1554E920B3928E00EA92C5 /* base64.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = base64.c; sourceTree = ""; };
+ DA1554EA20B3928E00EA92C5 /* mpw-algorithm.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = "mpw-algorithm.c"; sourceTree = ""; };
+ DA1554EB20B3928E00EA92C5 /* mpw-algorithm_v0.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = "mpw-algorithm_v0.c"; sourceTree = ""; };
+ DA1554EC20B3928E00EA92C5 /* mpw-types.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "mpw-types.h"; sourceTree = ""; };
+ DA1554ED20B3928E00EA92C5 /* mpw-util.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "mpw-util.h"; sourceTree = ""; };
+ DA1554EE20B3928E00EA92C5 /* mpw-marshal-util.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "mpw-marshal-util.h"; sourceTree = ""; };
+ DA1554EF20B3928E00EA92C5 /* mpw-algorithm_v3.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = "mpw-algorithm_v3.c"; sourceTree = ""; };
+ DA1554F120B392A100EA92C5 /* jni_mpw.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = jni_mpw.h; sourceTree = ""; };
+ DA1554F220B392A100EA92C5 /* jni_mpw.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = jni_mpw.c; sourceTree = ""; };
+/* End PBXFileReference section */
+
+/* Begin PBXGroup section */
+ DA1554D220B3924000EA92C5 = {
+ isa = PBXGroup;
+ children = (
+ DA1554F020B392A100EA92C5 /* jni */,
+ DA1554DD20B3928E00EA92C5 /* core */,
+ );
+ sourceTree = "";
+ };
+ DA1554DD20B3928E00EA92C5 /* core */ = {
+ isa = PBXGroup;
+ children = (
+ DA1554DE20B3928E00EA92C5 /* aes.c */,
+ DA1554DF20B3928E00EA92C5 /* mpw-algorithm.h */,
+ DA1554E020B3928E00EA92C5 /* base64.h */,
+ DA1554E120B3928E00EA92C5 /* mpw-marshal.c */,
+ DA1554E220B3928E00EA92C5 /* mpw-algorithm_v2.c */,
+ DA1554E320B3928E00EA92C5 /* mpw-types.c */,
+ DA1554E420B3928E00EA92C5 /* mpw-marshal-util.c */,
+ DA1554E520B3928E00EA92C5 /* mpw-util.c */,
+ DA1554E620B3928E00EA92C5 /* mpw-algorithm_v1.c */,
+ DA1554E720B3928E00EA92C5 /* aes.h */,
+ DA1554E820B3928E00EA92C5 /* mpw-marshal.h */,
+ DA1554E920B3928E00EA92C5 /* base64.c */,
+ DA1554EA20B3928E00EA92C5 /* mpw-algorithm.c */,
+ DA1554EB20B3928E00EA92C5 /* mpw-algorithm_v0.c */,
+ DA1554EC20B3928E00EA92C5 /* mpw-types.h */,
+ DA1554ED20B3928E00EA92C5 /* mpw-util.h */,
+ DA1554EE20B3928E00EA92C5 /* mpw-marshal-util.h */,
+ DA1554EF20B3928E00EA92C5 /* mpw-algorithm_v3.c */,
+ );
+ name = core;
+ path = ../../core/c;
+ sourceTree = "";
+ };
+ DA1554F020B392A100EA92C5 /* jni */ = {
+ isa = PBXGroup;
+ children = (
+ DA1554F120B392A100EA92C5 /* jni_mpw.h */,
+ DA1554F220B392A100EA92C5 /* jni_mpw.c */,
+ );
+ name = jni;
+ path = ../../core/java/algorithm/src/mpw/c;
+ sourceTree = "";
+ };
+/* End PBXGroup section */
+
+/* Begin PBXLegacyTarget section */
+ DA1554D720B3924000EA92C5 /* MasterPassword-JNI */ = {
+ isa = PBXLegacyTarget;
+ buildArgumentsString = ":masterpassword-algorithm:nativeGenHeaders";
+ buildConfigurationList = DA1554DA20B3924000EA92C5 /* Build configuration list for PBXLegacyTarget "MasterPassword-JNI" */;
+ buildPhases = (
+ );
+ buildToolPath = gradle;
+ buildWorkingDirectory = /Users/lhunath/Documents/workspace/lyndir/MasterPassword/gradle;
+ dependencies = (
+ );
+ name = "MasterPassword-JNI";
+ passBuildSettingsInEnvironment = 1;
+ productName = "MasterPassword-JNI";
+ };
+/* End PBXLegacyTarget section */
+
+/* Begin PBXProject section */
+ DA1554D320B3924000EA92C5 /* Project object */ = {
+ isa = PBXProject;
+ attributes = {
+ LastUpgradeCheck = 0930;
+ ORGANIZATIONNAME = "Maarten Billemont";
+ TargetAttributes = {
+ DA1554D720B3924000EA92C5 = {
+ CreatedOnToolsVersion = 9.3.1;
+ };
+ };
+ };
+ buildConfigurationList = DA1554D620B3924000EA92C5 /* Build configuration list for PBXProject "MasterPassword-JNI" */;
+ compatibilityVersion = "Xcode 9.3";
+ developmentRegion = en;
+ hasScannedForEncodings = 0;
+ knownRegions = (
+ en,
+ );
+ mainGroup = DA1554D220B3924000EA92C5;
+ projectDirPath = "";
+ projectRoot = "";
+ targets = (
+ DA1554D720B3924000EA92C5 /* MasterPassword-JNI */,
+ );
+ };
+/* End PBXProject section */
+
+/* Begin XCBuildConfiguration section */
+ DA1554D820B3924000EA92C5 /* Debug */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ HEADER_SEARCH_PATHS = (
+ "/Library/Java/JavaVirtualMachines/jdk1.8.0_161.jdk/Contents/Home/include/**",
+ );
+ };
+ name = Debug;
+ };
+ DA1554D920B3924000EA92C5 /* Release */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ HEADER_SEARCH_PATHS = (
+ "/Library/Java/JavaVirtualMachines/jdk1.8.0_161.jdk/Contents/Home/include/**",
+ );
+ };
+ name = Release;
+ };
+ DA1554DB20B3924000EA92C5 /* Debug */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ JAVA_HOME = /Library/Java/JavaVirtualMachines/jdk1.8.0_161.jdk/Contents/Home;
+ };
+ name = Debug;
+ };
+ DA1554DC20B3924000EA92C5 /* Release */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ JAVA_HOME = /Library/Java/JavaVirtualMachines/jdk1.8.0_161.jdk/Contents/Home;
+ };
+ name = Release;
+ };
+/* End XCBuildConfiguration section */
+
+/* Begin XCConfigurationList section */
+ DA1554D620B3924000EA92C5 /* Build configuration list for PBXProject "MasterPassword-JNI" */ = {
+ isa = XCConfigurationList;
+ buildConfigurations = (
+ DA1554D820B3924000EA92C5 /* Debug */,
+ DA1554D920B3924000EA92C5 /* Release */,
+ );
+ defaultConfigurationIsVisible = 0;
+ defaultConfigurationName = Release;
+ };
+ DA1554DA20B3924000EA92C5 /* Build configuration list for PBXLegacyTarget "MasterPassword-JNI" */ = {
+ isa = XCConfigurationList;
+ buildConfigurations = (
+ DA1554DB20B3924000EA92C5 /* Debug */,
+ DA1554DC20B3924000EA92C5 /* Release */,
+ );
+ defaultConfigurationIsVisible = 0;
+ defaultConfigurationName = Release;
+ };
+/* End XCConfigurationList section */
+ };
+ rootObject = DA1554D320B3924000EA92C5 /* Project object */;
+}
diff --git a/platform-darwin/MasterPassword.xcworkspace/contents.xcworkspacedata b/platform-darwin/MasterPassword.xcworkspace/contents.xcworkspacedata
index 4cd05f9b..d31ca6db 100644
--- a/platform-darwin/MasterPassword.xcworkspace/contents.xcworkspacedata
+++ b/platform-darwin/MasterPassword.xcworkspace/contents.xcworkspacedata
@@ -1,6 +1,9 @@
+
+