diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..dcd690d
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,31 @@
+/target/
+!.mvn/wrapper/maven-wrapper.jar
+
+/.idea/
+/.mvn/
+/mvnw
+/classes/
+/mvnw.cmd
+
+### STS ###
+.apt_generated
+.classpath
+.factorypath
+.project
+.settings
+.springBeans
+.sts4-cache
+
+### IntelliJ IDEA ###
+.idea
+*.iws
+*.iml
+*.ipr
+
+### NetBeans ###
+/nbproject/private/
+/build/
+/nbbuild/
+/dist/
+/nbdist/
+/.nb-gradle/
\ No newline at end of file
diff --git a/README.md b/README.md
new file mode 100644
index 0000000..49ff977
--- /dev/null
+++ b/README.md
@@ -0,0 +1,165 @@
+# 1. Introduction
+Java backend for TrustNet browser plugin
+## 1.1 Requirements
+1. Access to Indy pool
+2. libIndy v1.3.1
+# 2. API
+## 2.1 Create new account
+Creates new account. Sets up user wallet and cretes first `did`.
+```json
+{"operation" : "CREATE_ACCOUNT", "params" :{"username" : "xxxx", "password" : "yyyy"}}
+```
+Example response:
+```json
+{"status":"SUCCESS","value":{"username":"xxxxxx","walletname":"eb7a5aaf-9dfa-4e61-b5ed-eff9aaae2d8d"}}
+```
+## 2.2 Login to account
+Logs in to account, returns `token`
+```json
+{"operation" : "LOGIN", "params" :{"username" : "xxxxxx", "password" : "yyyy"}}
+```
+Example response:
+```json
+{"status":"SUCCESS","value":{"token":"66bd38e4-0e8d-46af-8b5c-2abada5f7eb7"}}
+```
+
+## 2.3 Create new DID
+Creates new `DID`
+```json
+{"operation" : "CREATE_DID", "params" :{"token" : "66bd38e4-0e8d-46af-8b5c-2abada5f7eb7"}}
+```
+Example response:
+```json
+{"status":"CREATED","value":{"did":"MsHajCPU2KjqVTYzgSYmwH","verkey":"CNeXKuzqdJMxbeC6sZHZCGyDjARqwQgkMaRTSX8CJ1p9"}}
+```
+
+## 2.4 Sign data
+Signs data.
+Example request:
+```json
+{"operation" : "SIGN_DATA", "params" :{"token" : "66bd38e4-0e8d-46af-8b5c-2abada5f7eb7", "did" : "MsHajCPU2KjqVTYzgSYmwH", "datatosign" :"testdata"}}
+```
+Example response:
+```json
+{"status":"SUCCESS","value":{"dataToSign":"testdata","wallet":"eb7a5aaf-9dfa-4e61-b5ed-eff9aaae2d8d","signature":"laOJ6ACNnBcRIwG+OtG1CE7FWtGK3WCiyndYZ84SN/KIjX5aMQpeyJ7ryfMiZ/0lrCE57jzcP3JC09MXCiHQAQ==","verkey":"CNeXKuzqdJMxbeC6sZHZCGyDjARqwQgkMaRTSX8CJ1p9","did":"MsHajCPU2KjqVTYzgSYmwH"}}
+```
+## 2.5 Verify signature
+Verifies signature.
+Example command:
+```json
+{"operation" : "VERIFY_SIGNATURE", "params" :{"token" : "66bd38e4-0e8d-46af-8b5c-2abada5f7eb7", "did" : "MsHajCPU2KjqVTYzgSYmwH", "message" :"testdata", "signature" :"laOJ6ACNnBcRIwG+OtG1CE7FWtGK3WCiyndYZ84SN/KIjX5aMQpeyJ7ryfMiZ/0lrCE57jzcP3JC09MXCiHQAQ=="}}
+```
+Example response:
+```json
+{"status":"SUCCESS","value":{"verified":true,"message":"testdata","signature":"laOJ6ACNnBcRIwG+OtG1CE7FWtGK3WCiyndYZ84SN/KIjX5aMQpeyJ7ryfMiZ/0lrCE57jzcP3JC09MXCiHQAQ==","did":"MsHajCPU2KjqVTYzgSYmwH"}}
+```
+
+## 2.6 Log out
+Logs out and invalidates the token.
+Example command:
+```json
+{"operation" : "LOGOUT" , "params" :{"token" : "66bd38e4-0e8d-46af-8b5c-2abada5f7eb7"}}
+```
+Example response:
+```json
+"status":"SUCCESS","value":{"loggedout":true}}
+```
+
+
+# 3. Standalone
+Make sure `RUN_AS_EXTENSION = false` in `Configuration.java`. Check that the `NETWORK_NAME` in `Configuration.java`
+matches with your Indy pool configuration.
+
+If `CREATE_USER`or `LOGIN` commands seem to hang decrease `workload`parameter in `userstore.java`.
+
+
+# 4. Browser extension
+Make sure `RUN_AS_EXTENSION = true` in `Configuration.java`.' Check that the `NETWORK_NAME` in `Configuration.java`
+matches with your Indy pool configuration.
+
+Build JAR and make it executable or create script that runs the JAR.
+## 4.1 Chrome configuration
+The following is for enabling for individual user.'
+Create file `fi.trustnet.browserplugin.json file` to `~/.config/google-chrome/NativeMessagingHosts' directory.
+File contents:
+```json
+ {
+ "name": "fi.trustnet.browserplugin",
+ "description": "TrustNet browser plugin backend",
+ "path": "PATH_TO_EXECUTABLE_JAR",
+ "type": "stdio",
+ "allowed_origins": [
+ "chrome-extension://YOUR_EXTENSION_ID/"
+ ]
+ }
+```
+
+
+## 4.2 Usage with Chrome
+### 4.2.1 Demo
+directory `example-app` contains example Crome App that can communicate with the native extension. To install it:
+1. Open Chrome
+2. go to `chrome://extensions/`
+3. Make sure Developer mode is enabled
+4. Select Load unpacked
+5. No the extension ID, make sure it is same as in `fi.trustnet.browserplugin.json` file, if not change the id in the file.
+6. Navigate to example-app directory and open it
+7. Go to `chrome://apps` and select TrustNet Demo
+
+### 4.2.1 Extension-background-native communication
+
+In background script have something like
+```code
+let port = null
+...
+chrome.runtime.onMessage.addListener((request) =>{
+ if(request.operation==="CONNECT" {
+ let hostName="fi.trustnet.browserplugin"
+ port = chrome.runtime,connectNative(hostName)
+ port.onMessage.addListener(onNativeMessage)
+ port.onDisconnect.addListener(onDisconnected)
+ }
+ if(request.operation==="CREATE_ACCOUNT){
+ port.postMessage(request)
+ }
+ //Other messages
+
+}
+
+const onNativeMessage = (message) => {
+ chrome.runtime.sendMessage({from : "background",
+ subject: "message",
+ message: "message"})
+
+}
+
+const onDisconnected = () => {
+ port=null
+ chrome.runtime.sendMessage({from : "background",
+ subject: "message",
+ message: "DISCONNECTED"})
+
+}
+```
+
+Code in Extension side:
+```code
+chrome.runtime.sendMessage(EXTENSION_ID, MESSAGE}
+```
+Examples:
+```code
+const connect=()=>{
+ chrome.runtime.sendMessage("kjhkdhldjldwlmlcwdd", {operation: "CONNECT"})
+}
+const createAccount=(username, password) => {
+ chrome.runtime.sendMessage("kjhkdhldjldwlmlcwdd",{"operation" : "CREATE_ACCOUNT", "params"} :{"username" : username, "password" : password}}
+}
+```
+Receive messages from background
+```code
+chrome.runtime.onMessage.addListener((message, sender)=> {
+ if(sender==="background") {
+ //handle messages from native extension
+ }
+}
+```
\ No newline at end of file
diff --git a/example-app/icon-128.png b/example-app/icon-128.png
new file mode 100644
index 0000000..c3bd2fd
Binary files /dev/null and b/example-app/icon-128.png differ
diff --git a/example-app/main.html b/example-app/main.html
new file mode 100644
index 0000000..9f9c6cf
--- /dev/null
+++ b/example-app/main.html
@@ -0,0 +1,14 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/example-app/main.js b/example-app/main.js
new file mode 100644
index 0000000..9193432
--- /dev/null
+++ b/example-app/main.js
@@ -0,0 +1,50 @@
+var port = null;
+
+function appendMessage(text) {
+ document.getElementById('response').innerHTML += "" + text + "
";
+}
+
+function updateUiState() {
+ if (port) {
+ document.getElementById('connect-button').style.display = 'none';
+ document.getElementById('input-text').style.display = 'block';
+ document.getElementById('send-message-button').style.display = 'block';
+ } else {
+ document.getElementById('connect-button').style.display = 'block';
+ document.getElementById('input-text').style.display = 'none';
+ document.getElementById('send-message-button').style.display = 'none';
+ }
+}
+
+function sendNativeMessage() {
+ message = JSON.parse(document.getElementById('input-text').value)
+ port.postMessage(message);
+ appendMessage("Sent message: " + JSON.stringify(message) + "");
+}
+
+function onNativeMessage(message) {
+ appendMessage("Received message: " + JSON.stringify(message) + "");
+}
+
+function onDisconnected() {
+ appendMessage("Failed to connect: " + chrome.runtime.lastError.message);
+ port = null;
+ updateUiState();
+}
+
+function connect() {
+ var hostName = "fi.trustnet.browserplugin";
+ appendMessage("Connecting")
+ port = chrome.runtime.connectNative(hostName);
+ port.onMessage.addListener(onNativeMessage);
+ port.onDisconnect.addListener(onDisconnected);
+ updateUiState();
+}
+
+document.addEventListener('DOMContentLoaded', function () {
+ document.getElementById('connect-button').addEventListener(
+ 'click', connect);
+ document.getElementById('send-message-button').addEventListener(
+ 'click', sendNativeMessage);
+ updateUiState();
+});
\ No newline at end of file
diff --git a/example-app/manifest.json b/example-app/manifest.json
new file mode 100644
index 0000000..e0dc89a
--- /dev/null
+++ b/example-app/manifest.json
@@ -0,0 +1,17 @@
+{
+ "name": "TrustNet Demo",
+ "version": "1.0",
+ "manifest_version": 2,
+ "description": "COmunication with native wallet app",
+ "app": {
+ "launch": {
+ "local_path": "main.html"
+ }
+ },
+ "icons": {
+ "128": "icon-128.png"
+ },
+ "permissions": [
+ "nativeMessaging"
+ ]
+}
\ No newline at end of file
diff --git a/pom.xml b/pom.xml
new file mode 100644
index 0000000..6651b89
--- /dev/null
+++ b/pom.xml
@@ -0,0 +1,127 @@
+
+
+
+ 4.0.0
+
+ fi.trustnet
+ plugin-backend
+ 1.0-SNAPSHOT
+
+ plugin-backend
+
+ http://www.example.com
+
+
+ UTF-8
+ 1.7
+ 1.7
+
+
+
+
+ junit
+ junit
+ 4.11
+ test
+
+
+
+ org.hyperledger
+ indy
+ 1.3.1
+ compile
+
+
+
+ com.fasterxml.jackson.core
+ jackson-databind
+ 2.9.4
+
+
+
+
+
+ org.xerial
+ sqlite-jdbc
+ 3.21.0.1
+
+
+
+
+ org.mindrot
+ jbcrypt
+ 0.4
+
+
+
+
+
+
+
+
+
+
+
+
+ maven-clean-plugin
+ 3.0.0
+
+
+
+ maven-resources-plugin
+ 3.0.2
+
+
+ maven-compiler-plugin
+ 3.7.0
+
+
+ maven-surefire-plugin
+ 2.20.1
+
+
+ maven-jar-plugin
+ 3.0.2
+
+
+ maven-install-plugin
+ 2.5.2
+
+
+ maven-deploy-plugin
+ 2.8.2
+
+
+
+
+
+ org.apache.maven.plugins
+ maven-compiler-plugin
+
+
+ 1.8
+
+
+
+ org.apache.maven.plugins
+ maven-dependency-plugin
+
+
+
+ copy-dependencies
+ package
+
+ copy-dependencies
+
+
+
+ runtime
+ ${project.build.directory}/dependency-jars/
+
+
+
+
+
+
+
diff --git a/src/main/java/fi/trustnet/browserextension/Agent.java b/src/main/java/fi/trustnet/browserextension/Agent.java
new file mode 100644
index 0000000..fe14be5
--- /dev/null
+++ b/src/main/java/fi/trustnet/browserextension/Agent.java
@@ -0,0 +1,40 @@
+package fi.trustnet.browserextension;
+
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.fasterxml.jackson.databind.node.ObjectNode;
+import fi.trustnet.browserextension.responses.CreateAccountResponse;
+import fi.trustnet.browserextension.responses.Response;
+import fi.trustnet.browserextension.user.Logger;
+import org.hyperledger.indy.sdk.wallet.Wallet;
+
+
+import static fi.trustnet.browserextension.Configuration.NETWORK_NAME;
+import static fi.trustnet.browserextension.Configuration.RUN_AS_EXTENSION;
+
+public class Agent {
+ private static final String FRIENDLY_NAME ="friendlyName";
+
+ public static String initializeAgent(String walletName, String username) throws Exception {
+
+ try {
+ Wallet.createWallet(NETWORK_NAME, walletName, "default", null, null).get();
+
+ ObjectMapper objectMapper = new ObjectMapper();
+ ObjectNode didMetadata = objectMapper.createObjectNode();
+ didMetadata.put(FRIENDLY_NAME, username + "@EdgeAgent");
+
+ DidCommands.createDid(walletName, didMetadata.toString(), null );
+
+ }
+ catch (Exception e) {
+
+ if (RUN_AS_EXTENSION)
+ Logger.writeToLog("initializeAgent " + e.getMessage());
+ else
+ System.out.println(e.getMessage());
+ throw e;
+ }
+
+ return walletName;
+ }
+}
diff --git a/src/main/java/fi/trustnet/browserextension/App.java b/src/main/java/fi/trustnet/browserextension/App.java
new file mode 100644
index 0000000..892b40b
--- /dev/null
+++ b/src/main/java/fi/trustnet/browserextension/App.java
@@ -0,0 +1,414 @@
+//https://github.com/ulymarins/chrome-native-messaging-java/blob/master/host-project/src/main/java/br/net/cartoriodigital/Application.java
+package fi.trustnet.browserextension;
+
+import com.fasterxml.jackson.databind.ObjectMapper;
+
+import fi.trustnet.browserextension.errors.ErrorCode;
+import fi.trustnet.browserextension.errors.ErrorMessage;
+import fi.trustnet.browserextension.user.*;
+import fi.trustnet.browserextension.responses.CreateAccountResponse;
+import fi.trustnet.browserextension.responses.LoginResponse;
+import fi.trustnet.browserextension.responses.LogoutResponse;
+import fi.trustnet.browserextension.responses.Response;
+import org.hyperledger.indy.sdk.LibIndy;
+
+import java.io.*;
+import java.util.LinkedHashMap;
+
+import static fi.trustnet.browserextension.CommandCodes.*;
+import static fi.trustnet.browserextension.Configuration.LIBINDY_LOCATION;
+import static fi.trustnet.browserextension.Configuration.RUN_AS_EXTENSION;
+import static fi.trustnet.browserextension.PayloadKeys.*;
+import static fi.trustnet.browserextension.StatusCodes.CREATED;
+import static fi.trustnet.browserextension.StatusCodes.ERROR;
+import static fi.trustnet.browserextension.errors.ExceptionMessage.createErrorMessageFromException;
+
+public class App
+{
+
+
+
+ private static ObjectMapper objectMapper;
+
+ public static void main( String[] args ) {
+
+
+ UserStore.initUserDb();
+ TokenStore.initTokenDb();
+
+ objectMapper = new ObjectMapper();
+
+ if (!LibIndy.isInitialized()) LibIndy.init(new File(LIBINDY_LOCATION));
+
+
+
+ try {
+ if (!RUN_AS_EXTENSION) {
+ System.out.println("enter commands, ctrl-c to exit");
+ BufferedReader br = null;
+ BufferedWriter bw = null;
+ InputStreamReader in= new InputStreamReader(System.in);
+ OutputStreamWriter out = new OutputStreamWriter(System.out);
+ br = new BufferedReader(in);
+ bw = new BufferedWriter(out);
+ while (true) {
+ String cmd = br.readLine();
+ String response = processInput(cmd);
+ bw.newLine();
+ bw.write(response);
+ bw.newLine();
+ bw.flush();
+ }
+
+ }
+ else {
+ while (true) {
+ byte[] msgLen = new byte[4];
+ System.in.read(msgLen);
+ int size = getInt(msgLen);
+ writeReqToFile("size " + size);
+ byte[] b = new byte[size];
+ System.in.read(b, 0, size);
+ writeReqToFile(new String(b, "UTF-8"));
+
+ String response = processInput(new String(b, "UTF-8"));
+
+ System.out.write(getBytes(response.length()));
+ System.out.write(response.getBytes("UTF-8"));
+ System.out.flush();
+ }
+ }
+
+ } catch (IOException e) {
+ if (RUN_AS_EXTENSION)
+ Logger.writeToLog("Exception in msg reader loop" + e.getMessage());
+ else
+ e.printStackTrace();
+ }
+ }
+
+ private static int getInt(byte[] bytes) {
+ return (bytes[3] << 24) & 0xff000000 | (bytes[2] << 16) & 0x00ff0000
+ | (bytes[1] << 8) & 0x0000ff00 | (bytes[0] << 0) & 0x000000ff;
+ }
+
+ private static byte[] getBytes(int length) {
+ byte[] bytes = new byte[4];
+ bytes[0] = (byte) (length & 0xFF);
+ bytes[1] = (byte) ((length >> 8) & 0xFF);
+ bytes[2] = (byte) ((length >> 16) & 0xFF);
+ bytes[3] = (byte) ((length >> 24) & 0xFF);
+ return bytes;
+ }
+
+ private static void writeReqToFile(String req) {
+ try {
+ FileWriter fw = new FileWriter("log.txt", true);
+ fw.write(req + "\n");
+ fw.flush();
+ fw.close();
+ }
+ catch (Exception e) {
+ }
+ }
+
+ private static String getWalletName(Object params) {
+ if (!(params instanceof LinkedHashMap)) {
+ return "";
+ }
+ String tokenId = ((LinkedHashMap)params).get(TOKEN).toString();
+ Token token = TokenStore.findTokenByTokenId(tokenId);
+ if (token == null) {
+ return "";
+ }
+ return UserStore.getWalletNameByUsername(token.getUsername());
+ }
+
+ private static String getDid(Object params) {
+ if (!(params instanceof LinkedHashMap)) {
+ return "";
+ }
+ return ((LinkedHashMap)params).get(DID).toString();
+ }
+
+ private static String getDataToSign(Object params) {
+ if (!(params instanceof LinkedHashMap)) {
+ return "";
+ }
+ return ((LinkedHashMap)params).get(DATA_TO_SIGN).toString();
+ }
+
+
+ private static String getMessage(Object params) {
+ if (!(params instanceof LinkedHashMap)) {
+ return "";
+ }
+ return ((LinkedHashMap)params).get(MESSAGE).toString();
+ }
+
+
+ private static String getSignature(Object params) {
+ if (!(params instanceof LinkedHashMap)) {
+ return "";
+ }
+ return ((LinkedHashMap)params).get(SIGNATURE).toString();
+ }
+
+
+ private static String getUsername(Object params) {
+ if (!(params instanceof LinkedHashMap)) {
+ return "";
+ }
+ return ((LinkedHashMap)params).get(USERNAME).toString();
+ }
+
+
+ private static String getPassword(Object params) {
+ if (!(params instanceof LinkedHashMap)) {
+ return "";
+ }
+ return ((LinkedHashMap)params).get(PASSWORD).toString();
+ }
+
+
+ private static String getToken(Object params) {
+ if (!(params instanceof LinkedHashMap)) {
+ return "";
+ }
+ return ((LinkedHashMap)params).getOrDefault(TOKEN, "").toString();
+ }
+
+ private static boolean isTokenValid(String tokenId) {
+ if (TokenStore.findTokenByTokenId(tokenId) == null ){
+ return false;
+ }
+ else {
+ return true;
+ }
+ }
+
+ private static boolean verifyParams(String opType, Object params) {
+ if (!(params instanceof LinkedHashMap)) {
+ return false;
+ }
+ switch (opType) {
+ case CREATE_DID : {
+ if (((LinkedHashMap)params).get(TOKEN) == null) {
+ return false;
+ }
+ else {
+ return true;
+ }
+ }
+
+ case SIGN_DATA : {
+ if (((LinkedHashMap)params).get(TOKEN) == null || ((LinkedHashMap)params).get(DID) == null
+ ||((LinkedHashMap)params).get(DATA_TO_SIGN) == null) {
+ return false;
+ }
+ else {
+ return true;
+ }
+ }
+ case VERIFY_SIGNATURE : {
+ if (((LinkedHashMap)params).get(TOKEN) == null || ((LinkedHashMap)params).get(DID) == null
+ ||((LinkedHashMap)params).get(SIGNATURE) == null || ((LinkedHashMap)params).get(MESSAGE) == null) {
+ return false;
+ }
+ else {
+ return true;
+ }
+ }
+ case GET_ALL_DIDS : {
+ if (((LinkedHashMap)params).get(TOKEN) == null) {
+ return false;
+ }
+ else {
+ return true;
+ }
+ }
+
+ case LOGIN :
+ case CREATE_ACCOUNT : {
+ if (((LinkedHashMap)params).get(USERNAME) == null || ((LinkedHashMap)params).get(PASSWORD) == null ) {
+ return false;
+ }
+ else {
+ return true;
+ }
+ }
+
+ case LOGOUT : {
+ if (((LinkedHashMap)params).get(TOKEN) == null) {
+ return false;
+ }
+ else {
+ return true;
+ }
+
+ }
+
+ }
+ return false;
+ }
+
+ private static String processInput(String input) {
+
+ try {
+ Command cmd = objectMapper.readValue(input, Command.class);
+ if (cmd.getOperation() == null)
+ throw new Exception();
+ Object params = cmd.getParams();
+ String walletName;
+ if (!cmd.getOperation().equals(LOGIN) && !cmd.getOperation().equals(CREATE_ACCOUNT)) {
+ if (!verifyParams(CREATE_DID, params)) {
+ return createErrorResponse(706, "Missing token");
+ }
+ if (!isTokenValid(getToken(params))) {
+ return createErrorResponse(705, "Unauthorized");
+ }
+ }
+ switch (cmd.getOperation()) {
+ case CREATE_DID : {
+ if (verifyParams(CREATE_DID,params)) {
+ walletName = getWalletName(params);
+ try {
+
+ DidParams didParams = DidCommands.createDid(walletName, null, null);
+ Response response = new Response();
+ response.setStatus(CREATED);
+ response.setValue(didParams);
+ return objectMapper.writeValueAsString(response);
+ }
+ catch (Exception e) {
+ return createErrorMessageFromException(e);
+ }
+ }
+ else return createErrorResponse(700, "wrong parameters");
+ }
+ case SIGN_DATA : {
+ if (verifyParams(SIGN_DATA,params)) {
+ walletName = getWalletName(params);
+ String did = getDid(params);
+ String dataToSign = getDataToSign(params);
+ return Signature.Base64EncodedSignature(walletName,did, dataToSign);
+ }
+ else return createErrorResponse(700, "wrong parameters");
+ }
+ case VERIFY_SIGNATURE : {
+ if (verifyParams(VERIFY_SIGNATURE, params)) {
+ walletName = getWalletName(params);
+ String did = getDid(params);
+ String signature = getSignature(params);
+ String message = getMessage(params);
+ return Signature.VerifyBase64EncodedSignature(walletName, signature, message, did);
+ }
+ else return createErrorResponse(700, "wrong parameters");
+ }
+
+ case GET_ALL_DIDS : {
+ if (verifyParams(GET_ALL_DIDS, params)) {
+ walletName = getWalletName(params);
+ return DidCommands.getAllDids(walletName);
+ }
+ }
+
+ case CREATE_ACCOUNT : {
+ if (verifyParams(CREATE_ACCOUNT, params)) {
+ String username = getUsername(params);
+ String password = getPassword(params);
+ if (UserStore.findUserByUsername(username) != null) {
+ return createErrorResponse(703, "user with name " + username + " already exitss");
+ }
+ UserAccount account = new UserAccount();
+ account.setUsername(username);
+ //userstore hashes pwd before saving
+ account.setPassword(password);
+ account.setWalletname(java.util.UUID.randomUUID().toString());
+ UserStore.storeNewUser(account);
+
+ try {
+ Agent.initializeAgent(account.getWalletname(), account.getUsername());
+
+ CreateAccountResponse createAccountResponse = new CreateAccountResponse();
+ createAccountResponse.setUsername(username);
+ createAccountResponse.setWalletname(account.getWalletname());
+ Response resp = new Response(StatusCodes.SUCCESS, createAccountResponse);
+ return getJsonValue(resp);
+ }
+ catch (Exception e){
+ UserStore.deleteUser(account.getUsername());
+ return createErrorResponse(800, "Could not initialize agent");
+ }
+ }
+ }
+
+ case LOGIN : {
+ if (verifyParams(LOGIN, params)) {
+ String username = getUsername(params);
+ String password = getPassword(params);
+ if (UserStore.login(username, password)) {
+ Token token = new Token();
+ token.setToken(java.util.UUID.randomUUID().toString());
+ token.setUsername(username);
+ TokenStore.storeNewToken(token);
+ LoginResponse loginResponse = new LoginResponse();
+ loginResponse.setToken(token.getToken());
+ Response resp = new Response(StatusCodes.SUCCESS, loginResponse);
+ return getJsonValue(resp);
+ }
+ return createErrorResponse(704, "wrong username or password");
+ }
+ }
+
+ case LOGOUT : {
+ if (verifyParams(LOGOUT, params)) {
+ String tokenId = getToken(params);
+ if (TokenStore.findTokenByTokenId(tokenId) != null) {
+ TokenStore.removeToken(tokenId);
+ LogoutResponse logoutResponse = new LogoutResponse();
+ logoutResponse.setLoggedout(true);
+ Response resp = new Response(StatusCodes.SUCCESS, logoutResponse);
+ return getJsonValue(resp);
+ }
+ else {
+ return createErrorResponse(705, "Incorrect token");
+ }
+ }
+ }
+
+ default : {
+ return createErrorResponse(701, "unknown operation");
+ }
+ }
+
+
+ }
+ catch (Exception e) {
+ //e.printStackTrace();
+ return createErrorResponse(700, "malformed request");
+ }
+
+ }
+
+ private static String createErrorResponse(int code, String description) {
+
+ ErrorMessage error = new ErrorMessage(ErrorCode.valueOf(code).toString(), description);
+ Response response = new Response(ERROR, error);
+ return getJsonValue(response);
+ }
+
+
+ public static String getJsonValue(Object obj) {
+ ObjectMapper objectMapper = new ObjectMapper();
+ try {
+ return objectMapper.writeValueAsString(obj);
+ }
+ catch (Exception e) {
+ return "{\"status\":\"ERROR\",\"value\":{\"errorcode\":\"INTERNAL_ERROR\",\"description\":\"ObjectMapper exception\"}}";
+ }
+ }
+
+
+
+}
diff --git a/src/main/java/fi/trustnet/browserextension/Command.java b/src/main/java/fi/trustnet/browserextension/Command.java
new file mode 100644
index 0000000..83c9cbe
--- /dev/null
+++ b/src/main/java/fi/trustnet/browserextension/Command.java
@@ -0,0 +1,29 @@
+package fi.trustnet.browserextension;
+
+import java.util.LinkedHashMap;
+
+
+public class Command {
+ private String operation;
+ private Object params;
+
+ public Command() {
+ this.params = new LinkedHashMap<>();
+ }
+
+ public String getOperation() {
+ return operation;
+ }
+
+ public void setOperation(String operation) {
+ this.operation = operation;
+ }
+
+ public Object getParams() {
+ return params;
+ }
+
+ public void setParams(Object params) {
+ this.params = params;
+ }
+}
diff --git a/src/main/java/fi/trustnet/browserextension/CommandCodes.java b/src/main/java/fi/trustnet/browserextension/CommandCodes.java
new file mode 100644
index 0000000..e54157b
--- /dev/null
+++ b/src/main/java/fi/trustnet/browserextension/CommandCodes.java
@@ -0,0 +1,14 @@
+package fi.trustnet.browserextension;
+
+public class CommandCodes {
+ public static final String CREATE_WALLET = "CREATE_WALLET";
+ public static final String CREATE_DID = "CREATE_DID";
+ public static final String SIGN_DATA = "SIGN_DATA";
+ public static final String VERIFY_SIGNATURE = "VERIFY_SIGNATURE";
+ public static final String GET_ALL_DIDS = "GET_ALL_DIDS";
+ public static final String CREATE_ACCOUNT = "CREATE_ACCOUNT";
+ public static final String LOGIN = "LOGIN";
+ public static final String LOGOUT = "LOGOUT";
+
+
+}
diff --git a/src/main/java/fi/trustnet/browserextension/Configuration.java b/src/main/java/fi/trustnet/browserextension/Configuration.java
new file mode 100644
index 0000000..2991643
--- /dev/null
+++ b/src/main/java/fi/trustnet/browserextension/Configuration.java
@@ -0,0 +1,12 @@
+package fi.trustnet.browserextension;
+
+public class Configuration {
+ public static final String WALLET_BASEPATH = "jdbc:sqlite:/home/samuli/.indy_client/wallet/";
+ public static final String USER_DB_FILE = "/home/samuli/.indy_client/users.db";
+ public static final String TOKEN_DB_FILE = "/home/samuli/.indy_client/tokens.db";
+ public static final String LIBINDY_LOCATION = "./lib/libindy.so";
+ //set to true before creating jar for browser extension
+ public static final boolean RUN_AS_EXTENSION = false;
+
+ public static final String NETWORK_NAME = "default_pool";
+}
diff --git a/src/main/java/fi/trustnet/browserextension/DidCommands.java b/src/main/java/fi/trustnet/browserextension/DidCommands.java
new file mode 100644
index 0000000..0d1878d
--- /dev/null
+++ b/src/main/java/fi/trustnet/browserextension/DidCommands.java
@@ -0,0 +1,87 @@
+package fi.trustnet.browserextension;
+
+import fi.trustnet.browserextension.user.Logger;
+import org.hyperledger.indy.sdk.did.Did;
+import org.hyperledger.indy.sdk.did.DidJSONParameters;
+import org.hyperledger.indy.sdk.did.DidResults;
+import org.hyperledger.indy.sdk.pool.Pool;
+import org.hyperledger.indy.sdk.wallet.Wallet;
+
+
+import static fi.trustnet.browserextension.Configuration.NETWORK_NAME;
+import static fi.trustnet.browserextension.Configuration.RUN_AS_EXTENSION;
+
+public class DidCommands {
+
+
+ public static DidParams createDid(String walletName, String didMetadata, String serviceUrl) throws Exception {
+ Pool pool = null;
+ Wallet wallet = null;
+ try {
+ pool = Pool.openPoolLedger(NETWORK_NAME, "{}").get();
+ wallet = Wallet.openWallet(walletName, null, null).get();
+
+ // USE GUID as seed, should be replaced with real PRNG;
+ String seed = java.util.UUID.randomUUID().toString();
+ seed = seed.replaceAll("-", "");
+
+
+ DidJSONParameters.CreateAndStoreMyDidJSONParameter createAndStoreMyDidJSONParameter = new DidJSONParameters.CreateAndStoreMyDidJSONParameter(null, seed , null, null);
+ DidResults.CreateAndStoreMyDidResult createAndStoreMyDidResult = Did.createAndStoreMyDid(wallet, createAndStoreMyDidJSONParameter.toJson()).get();
+
+
+
+ String did = createAndStoreMyDidResult.getDid();
+ String verkey = createAndStoreMyDidResult.getVerkey();
+
+ if (didMetadata != null) {
+ Did.setDidMetadata(wallet, did, didMetadata);
+ }
+ if (serviceUrl != null) {
+ Did.setEndpointForDid(wallet, did, serviceUrl, null);
+ }
+
+ DidParams didParams = new DidParams();
+ didParams.setDid(did);
+ didParams.setVerkey(verkey);
+ didParams.setUrl(serviceUrl);
+ didParams.setDidMetadata(didMetadata);
+
+ wallet.closeWallet().get();
+ wallet = null;
+ pool.closePoolLedger().get();
+ pool = null;
+
+ return didParams;
+ }
+ catch (Exception e) {
+ try {
+ if (RUN_AS_EXTENSION)
+ Logger.writeToLog("createDid" + e.getMessage());
+ else
+ System.out.println(e.getMessage());
+
+ if (wallet != null)
+ wallet.closeWallet().get();
+ if (pool != null)
+ pool.closePoolLedger().get();
+ throw e;
+
+ }
+ catch (Exception ex) {
+ if (RUN_AS_EXTENSION)
+ Logger.writeToLog("createDid" + ex.getMessage());
+ else
+ System.out.println(ex.getMessage());
+
+ throw ex;
+ }
+ }
+ }
+
+ public static String getAllDids(String walletName) {
+ WalletDbReader walletDbReader = new WalletDbReader();
+ return walletDbReader.getAllDids(walletName);
+ }
+
+}
diff --git a/src/main/java/fi/trustnet/browserextension/DidList.java b/src/main/java/fi/trustnet/browserextension/DidList.java
new file mode 100644
index 0000000..83e2912
--- /dev/null
+++ b/src/main/java/fi/trustnet/browserextension/DidList.java
@@ -0,0 +1,20 @@
+package fi.trustnet.browserextension;
+
+import java.util.LinkedList;
+import java.util.List;
+
+public class DidList {
+ private List dids;
+
+ public DidList() {
+ this.dids = new LinkedList<>();
+ }
+
+ public List getDids() {
+ return dids;
+ }
+
+ public void setDids(List dids) {
+ this.dids = dids;
+ }
+}
diff --git a/src/main/java/fi/trustnet/browserextension/DidParams.java b/src/main/java/fi/trustnet/browserextension/DidParams.java
new file mode 100644
index 0000000..8232f4a
--- /dev/null
+++ b/src/main/java/fi/trustnet/browserextension/DidParams.java
@@ -0,0 +1,47 @@
+package fi.trustnet.browserextension;
+
+import com.fasterxml.jackson.annotation.JsonInclude;
+
+@JsonInclude(JsonInclude.Include.NON_NULL)
+public class DidParams {
+ private String did;
+ private String verkey;
+ private String url;
+ private Object didMetadata;
+
+ public DidParams() {
+ }
+
+ public String getDid() {
+ return did;
+ }
+
+ public void setDid(String did) {
+ this.did = did;
+ }
+
+ public String getVerkey() {
+ return verkey;
+ }
+
+ public void setVerkey(String verkey) {
+ this.verkey = verkey;
+ }
+
+ public String getUrl() {
+ return url;
+ }
+
+ public void setUrl(String url) {
+ this.url = url;
+ }
+
+ public Object getDidMetadata() {
+ return didMetadata;
+ }
+
+ public void setDidMetadata(Object didMetadata) {
+ this.didMetadata = didMetadata;
+ }
+}
+
diff --git a/src/main/java/fi/trustnet/browserextension/PayloadKeys.java b/src/main/java/fi/trustnet/browserextension/PayloadKeys.java
new file mode 100644
index 0000000..9fb2a38
--- /dev/null
+++ b/src/main/java/fi/trustnet/browserextension/PayloadKeys.java
@@ -0,0 +1,14 @@
+package fi.trustnet.browserextension;
+
+public class PayloadKeys {
+ public static final String WALLET_NAME = "walletname";
+ public static final String DID = "did";
+ public static final String DATA_TO_SIGN = "datatosign";
+ public static final String SIGNATURE = "signature";
+ public static final String MESSAGE = "message";
+ public static final String USERNAME = "username";
+ public static final String PASSWORD = "password";
+ public static final String TOKEN = "token";
+
+
+}
diff --git a/src/main/java/fi/trustnet/browserextension/Signature.java b/src/main/java/fi/trustnet/browserextension/Signature.java
new file mode 100644
index 0000000..2d19d85
--- /dev/null
+++ b/src/main/java/fi/trustnet/browserextension/Signature.java
@@ -0,0 +1,118 @@
+package fi.trustnet.browserextension;
+
+import fi.trustnet.browserextension.responses.Response;
+import fi.trustnet.browserextension.responses.SignatureResult;
+import fi.trustnet.browserextension.responses.SignatureVerificationResult;
+import fi.trustnet.browserextension.user.Logger;
+import org.hyperledger.indy.sdk.crypto.Crypto;
+import org.hyperledger.indy.sdk.did.Did;
+import org.hyperledger.indy.sdk.pool.Pool;
+import org.hyperledger.indy.sdk.wallet.Wallet;
+
+import java.util.Base64;
+
+
+import static fi.trustnet.browserextension.App.getJsonValue;
+import static fi.trustnet.browserextension.Configuration.NETWORK_NAME;
+import static fi.trustnet.browserextension.Configuration.RUN_AS_EXTENSION;
+import static fi.trustnet.browserextension.errors.ExceptionMessage.createErrorMessageFromException;
+
+public class Signature {
+
+ public static String Base64EncodedSignature(String walletName, String did, String dataToSign) {
+ Pool pool =null;
+ Wallet wallet = null;
+ try {
+ pool = Pool.openPoolLedger(NETWORK_NAME, "{}").get();
+ wallet = Wallet.openWallet(walletName, null, null).get();
+ String key = Did.keyForLocalDid(wallet, did).get();
+ byte[] signed = Crypto.cryptoSign(wallet, key,dataToSign.getBytes()).get();
+ byte[] encoded = Base64.getEncoder().encode(signed);
+ wallet.closeWallet().get();
+ wallet = null;
+ pool.closePoolLedger().get();
+ pool = null;
+
+
+ SignatureResult signatureResult = new SignatureResult();
+ signatureResult.setDid(did);
+ signatureResult.setVerkey(key);
+ signatureResult.setSignature(new String(encoded));
+ signatureResult.setDataToSign(dataToSign);
+ signatureResult.setWallet(walletName);
+ Response response = new Response(StatusCodes.SUCCESS,signatureResult);
+
+ return getJsonValue(response);
+ }
+ catch (Exception e) {
+ try{
+ if (RUN_AS_EXTENSION)
+ Logger.writeToLog("Base64EncodedSignature" + e.getMessage());
+ else
+ System.out.println(e.getMessage());
+
+ if (pool != null)
+ pool.closePoolLedger().get();
+ if (wallet != null)
+ wallet.closeWallet().get();
+ return createErrorMessageFromException(e);
+ }
+ catch (Exception ex) {
+ if (RUN_AS_EXTENSION)
+ Logger.writeToLog("Base64EncodedSignature" + ex.getMessage());
+ else
+ System.out.println(ex.getMessage());
+ return createErrorMessageFromException(ex);
+ }
+ }
+ }
+ public static String VerifyBase64EncodedSignature(String walletName, String signature, String message, String did) {
+ Pool pool = null;
+ Wallet wallet = null;
+ try {
+ pool = Pool.openPoolLedger(NETWORK_NAME, "{}").get();
+ wallet = Wallet.openWallet(walletName, null, null).get();
+ String key = Did.keyForLocalDid(wallet, did).get();
+ Boolean verified = Crypto.cryptoVerify(key, message.getBytes(), Base64.getDecoder().decode(signature)).get();
+ wallet.closeWallet().get();
+ pool.closePoolLedger().get();
+
+ SignatureVerificationResult signatureVerificationResult = new SignatureVerificationResult();
+ signatureVerificationResult.setDid(did);
+ signatureVerificationResult.setMessage(message);
+ signatureVerificationResult.setVerified(verified);
+ signatureVerificationResult.setSignature(signature);
+
+
+ if (verified) {
+ Response response = new Response(StatusCodes.SUCCESS, signatureVerificationResult);
+ return getJsonValue(response);
+ }
+ else {
+ Response response = new Response(StatusCodes.FAIL, signatureVerificationResult);
+ return getJsonValue(response);
+ }
+ }
+ catch (Exception e){
+ if (RUN_AS_EXTENSION)
+ Logger.writeToLog("VerifyBase64EncodedSignature" + e.getMessage());
+ else
+ System.out.println(e.getMessage());
+ try {
+ if (wallet != null)
+ wallet.closeWallet().get();
+ if (pool != null)
+ pool.closePoolLedger().get();
+ }
+ catch (Exception ex) {
+ if (RUN_AS_EXTENSION)
+ Logger.writeToLog("Base64EncodedSignature" + ex.getMessage());
+ else
+ System.out.println(ex.getMessage());
+
+ return createErrorMessageFromException(ex);
+ }
+ return createErrorMessageFromException(e);
+ }
+ }
+}
diff --git a/src/main/java/fi/trustnet/browserextension/StatusCodes.java b/src/main/java/fi/trustnet/browserextension/StatusCodes.java
new file mode 100644
index 0000000..6e0b7ef
--- /dev/null
+++ b/src/main/java/fi/trustnet/browserextension/StatusCodes.java
@@ -0,0 +1,8 @@
+package fi.trustnet.browserextension;
+
+public class StatusCodes {
+ public static final String SUCCESS = "SUCCESS";
+ public static final String CREATED = "CREATED";
+ public static final String ERROR = "ERROR";
+ public static final String FAIL = "FAIL";
+}
diff --git a/src/main/java/fi/trustnet/browserextension/WalletDbReader.java b/src/main/java/fi/trustnet/browserextension/WalletDbReader.java
new file mode 100644
index 0000000..930b2a8
--- /dev/null
+++ b/src/main/java/fi/trustnet/browserextension/WalletDbReader.java
@@ -0,0 +1,64 @@
+package fi.trustnet.browserextension;
+
+import com.fasterxml.jackson.databind.ObjectMapper;
+import fi.trustnet.browserextension.responses.Response;
+import fi.trustnet.browserextension.user.Logger;
+
+import java.sql.*;
+
+import static fi.trustnet.browserextension.App.getJsonValue;
+import static fi.trustnet.browserextension.Configuration.RUN_AS_EXTENSION;
+import static fi.trustnet.browserextension.Configuration.WALLET_BASEPATH;
+import static fi.trustnet.browserextension.errors.ExceptionMessage.createErrorMessageFromException;
+
+public class WalletDbReader {
+
+
+ private Connection connect(String walletName) {
+ // SQLite connection string
+ Connection conn = null;
+ try {
+ Class.forName("org.sqlite.JDBC");
+ String url = WALLET_BASEPATH + walletName + "/sqlite.db";
+
+ try {
+ conn = DriverManager.getConnection(url);
+ } catch (SQLException e) {
+ if (RUN_AS_EXTENSION)
+ Logger.writeToLog("WalletDbReader connect" + e.getMessage());
+ else System.out.println(e.getMessage());
+ }
+ } catch (Exception e) {
+ if (RUN_AS_EXTENSION)
+ Logger.writeToLog("WalletDbReader connect" + e.getMessage());
+ else System.out.println(e.getMessage());
+ }
+ return conn;
+ }
+
+
+ public String getAllDids(String walletName){
+ String sql = "SELECT * FROM wallet WHERE KEY LIKE \"my%\"";
+ ObjectMapper objectMapper = new ObjectMapper();
+ try (Connection conn = this.connect(walletName);
+ Statement stmt = conn.createStatement();
+ ResultSet rs = stmt.executeQuery(sql)) {
+
+ DidList didList = new DidList();
+ // loop through the result set
+ while (rs.next()) {
+ DidParams didParams = objectMapper.readValue(rs.getString("value"), DidParams.class);
+ didList.getDids().add(didParams);
+ }
+ Response response = new Response(StatusCodes.SUCCESS,didList);
+
+ return getJsonValue(response);
+ } catch (Exception e) {
+ if (RUN_AS_EXTENSION)
+ Logger.writeToLog("WalletDbReader getAllDids" + e.getMessage());
+ else System.out.println(e.getMessage());
+
+ return createErrorMessageFromException(e);
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/main/java/fi/trustnet/browserextension/errors/ErrorCode.java b/src/main/java/fi/trustnet/browserextension/errors/ErrorCode.java
new file mode 100644
index 0000000..ca757e9
--- /dev/null
+++ b/src/main/java/fi/trustnet/browserextension/errors/ErrorCode.java
@@ -0,0 +1,275 @@
+package fi.trustnet.browserextension.errors;
+
+import java.util.HashMap;
+import java.util.Map;
+
+
+
+/**
+ * Enumeration of error codes returned by the indy SDK.
+ */
+public enum ErrorCode {
+
+ /**
+ * Success
+ */
+ Success(0),
+
+ // Common errors
+
+ /**
+ * Caller passed invalid value as param 1 (null, invalid json and etc..)
+ */
+ CommonInvalidParam1(100),
+
+ /**
+ * Caller passed invalid value as param 2 (null, invalid json and etc..)
+ */
+ CommonInvalidParam2(101),
+
+ /**
+ * Caller passed invalid value as param 3 (null, invalid json and etc..)
+ */
+ CommonInvalidParam3(102),
+
+ /**
+ * Caller passed invalid value as param 4 (null, invalid json and etc..)
+ */
+ CommonInvalidParam4(103),
+
+ /**
+ * Caller passed invalid value as param 5 (null, invalid json and etc..)
+ */
+ CommonInvalidParam5(104),
+
+ /**
+ * Caller passed invalid value as param 6 (null, invalid json and etc..)
+ */
+ CommonInvalidParam6(105),
+
+ /**
+ * Caller passed invalid value as param 7 (null, invalid json and etc..)
+ */
+ CommonInvalidParam7(106),
+
+ /**
+ * Caller passed invalid value as param 8 (null, invalid json and etc..)
+ */
+ CommonInvalidParam8(107),
+
+ /**
+ * Caller passed invalid value as param 9 (null, invalid json and etc..)
+ */
+ CommonInvalidParam9(108),
+
+ /**
+ * Caller passed invalid value as param 10 (null, invalid json and etc..)
+ */
+ CommonInvalidParam10(109),
+
+ /**
+ * Caller passed invalid value as param 11 (null, invalid json and etc..)
+ */
+ CommonInvalidParam11(110),
+
+ /**
+ * Caller passed invalid value as param 12 (null, invalid json and etc..)
+ */
+ CommonInvalidParam12(111),
+
+ /**
+ * Invalid library state was detected in runtime. It signals library bug
+ */
+ CommonInvalidState(112),
+
+ /**
+ * Object (json, config, key, claim and etc...) passed by library caller has invalid structure
+ */
+ CommonInvalidStructure(113),
+
+ /**
+ * IO ErrorMessage
+ */
+ CommonIOError(114),
+
+ // Wallet errors
+
+ /**
+ * Caller passed invalid wallet handle
+ */
+ WalletInvalidHandle(200),
+
+ /**
+ * Unknown type of wallet was passed on create_wallet
+ */
+ WalletUnknownTypeError(201),
+
+ /**
+ * Attempt to register already existing wallet type
+ */
+ WalletTypeAlreadyRegisteredError(202),
+
+ /**
+ * Attempt to create wallet with name used for another exists wallet
+ */
+ WalletAlreadyExistsError(203),
+
+ /**
+ * Requested entity id isn't present in wallet
+ */
+ WalletNotFoundError(204),
+
+ /**
+ * Trying to use wallet with pool that has different name
+ */
+ WalletIncompatiblePoolError(205),
+
+ /**
+ * Trying to open wallet that was opened already
+ */
+ WalletAlreadyOpenedError(206),
+
+ /**
+ * Attempt to open encrypted wallet with invalid credentials
+ */
+ WalletAccessFailed(207),
+
+ // Ledger errors
+
+ /**
+ * Trying to open pool ledger that wasn't created before
+ */
+ PoolLedgerNotCreatedError(300),
+
+ /**
+ * Caller passed invalid pool ledger handle
+ */
+ PoolLedgerInvalidPoolHandle(301),
+
+ /**
+ * Pool ledger terminated
+ */
+ PoolLedgerTerminated(302),
+
+ /**
+ * No concensus during ledger operation
+ */
+ LedgerNoConsensusError(303),
+
+ /**
+ * Attempt to send transaction without the necessary privileges
+ */
+ LedgerSecurityError(305),
+
+ /**
+ * Attempt to create pool ledger config with name used for another existing pool
+ */
+ PoolLedgerConfigAlreadyExistsError(306),
+
+ /**
+ * Timeout for action
+ */
+ PoolLedgerTimeout(307),
+
+ // Crypto errors
+
+ /**
+ * Revocation registry is full and creation of new registry is necessary
+ */
+ AnoncredsRevocationRegistryFullError(400),
+
+ /**
+ * ???
+ */
+ AnoncredsInvalidUserRevocIndex(401),
+
+ /**
+ * ???
+ */
+ AnoncredsAccumulatorIsFull(402),
+
+ /**
+ * ???
+ */
+ AnoncredsNotIssuedError(403),
+
+ /**
+ * Attempt to generate master secret with dupplicated name
+ */
+ AnoncredsMasterSecretDuplicateNameError(404),
+
+ /**
+ * ???
+ */
+ AnoncredsProofRejected(405),
+
+ /**
+ * Attempt to use a revoked claim.
+ */
+ AnoncredsClaimRevoked(406),
+
+ /**
+ * Attempt to create claim definition with duplicated did schema pair.
+ */
+ AnoncredsClaimDefAlreadyExistsError(407),
+
+ // Crypto errors
+
+ /**
+ * Unknown format of DID entity keys
+ */
+ UnknownCryptoTypeError(500),
+
+
+ /**
+ * Attempt to create duplicate did.
+ */
+ DidAlreadyExistsError(600),
+
+ //Added own error codes
+ MalformedRequest(700),
+ UnknownCommand(701),
+ GenericError(702),
+ UserAlreadyExists(703),
+ WrongUsernameOrPssword(704),
+ Unauthorized(705),
+ MissingToken(706),
+ InternalServerError(800);
+
+ private int value;
+ private static Map map = new HashMap();
+
+ private ErrorCode(int value) {
+
+ this.value = value;
+ }
+
+ static {
+
+ for (ErrorCode errorCode : ErrorCode.values()) {
+
+ map.put(Integer.valueOf(errorCode.value), errorCode);
+ }
+ }
+
+ /**
+ * Gets the ErrorCode that corresponds to the specified int value.
+ *
+ * @param value The integer to get the error code for.
+ * @return The ErrorCode that corresponds to the specified integer.
+ */
+ public static ErrorCode valueOf(int value) {
+
+ return map.get(Integer.valueOf(value));
+ }
+
+ /**
+ * Gets the integer value for a specific ErrorCode.
+ *
+ * @return The integer value of the ErrorCode.
+ */
+ public int value() {
+
+ return this.value;
+ }
+}
diff --git a/src/main/java/fi/trustnet/browserextension/errors/ErrorMessage.java b/src/main/java/fi/trustnet/browserextension/errors/ErrorMessage.java
new file mode 100644
index 0000000..3594eb3
--- /dev/null
+++ b/src/main/java/fi/trustnet/browserextension/errors/ErrorMessage.java
@@ -0,0 +1,32 @@
+package fi.trustnet.browserextension.errors;
+
+public class ErrorMessage {
+ private String errorcode;
+ private String Description;
+
+ public ErrorMessage(String errorcode, String description) {
+ this.errorcode = errorcode;
+ Description = description;
+ }
+
+ public ErrorMessage() {
+ }
+
+ public String getErrorcode() {
+ return errorcode;
+ }
+
+ public void setErrorcode(String errorcode) {
+ this.errorcode = errorcode;
+ }
+
+ public String getDescription() {
+ return Description;
+ }
+
+ public void setDescription(String description) {
+ Description = description;
+ }
+
+
+}
diff --git a/src/main/java/fi/trustnet/browserextension/errors/ExceptionMessage.java b/src/main/java/fi/trustnet/browserextension/errors/ExceptionMessage.java
new file mode 100644
index 0000000..146c6fe
--- /dev/null
+++ b/src/main/java/fi/trustnet/browserextension/errors/ExceptionMessage.java
@@ -0,0 +1,30 @@
+package fi.trustnet.browserextension.errors;
+
+
+import org.hyperledger.indy.sdk.IndyException;
+import fi.trustnet.browserextension.responses.Response;
+
+
+import static com.sun.xml.internal.ws.api.message.Packet.Status.Response;
+import static fi.trustnet.browserextension.App.getJsonValue;
+import static fi.trustnet.browserextension.StatusCodes.ERROR;
+
+
+public class ExceptionMessage {
+ public static String createErrorMessageFromException(Exception e) {
+ if (e.getCause() != null && IndyException.class.isAssignableFrom(e.getCause().getClass())) {
+ int errCode = ((IndyException)(e.getCause())).getSdkErrorCode();
+ String description = ((IndyException)(e.getCause())).getMessage();
+ return createErrorResponse(errCode, description);
+ }
+ return createErrorResponse(702, e.getMessage());
+ }
+
+ private static String createErrorResponse(int code, String description) {
+
+ ErrorMessage error = new ErrorMessage(ErrorCode.valueOf(code).toString(), description);
+ Response response = new Response(ERROR, error);
+ return getJsonValue(response);
+ }
+
+}
diff --git a/src/main/java/fi/trustnet/browserextension/responses/CreateAccountResponse.java b/src/main/java/fi/trustnet/browserextension/responses/CreateAccountResponse.java
new file mode 100644
index 0000000..c121bd3
--- /dev/null
+++ b/src/main/java/fi/trustnet/browserextension/responses/CreateAccountResponse.java
@@ -0,0 +1,25 @@
+package fi.trustnet.browserextension.responses;
+
+public class CreateAccountResponse {
+ private String username;
+ private String walletname;
+
+ public CreateAccountResponse() {
+ }
+
+ public String getUsername() {
+ return username;
+ }
+
+ public void setUsername(String username) {
+ this.username = username;
+ }
+
+ public String getWalletname() {
+ return walletname;
+ }
+
+ public void setWalletname(String walletname) {
+ this.walletname = walletname;
+ }
+}
diff --git a/src/main/java/fi/trustnet/browserextension/responses/LoginResponse.java b/src/main/java/fi/trustnet/browserextension/responses/LoginResponse.java
new file mode 100644
index 0000000..1d17e8d
--- /dev/null
+++ b/src/main/java/fi/trustnet/browserextension/responses/LoginResponse.java
@@ -0,0 +1,16 @@
+package fi.trustnet.browserextension.responses;
+
+public class LoginResponse {
+ private String token;
+
+ public LoginResponse() {
+ }
+
+ public String getToken() {
+ return token;
+ }
+
+ public void setToken(String token) {
+ this.token = token;
+ }
+}
diff --git a/src/main/java/fi/trustnet/browserextension/responses/LogoutResponse.java b/src/main/java/fi/trustnet/browserextension/responses/LogoutResponse.java
new file mode 100644
index 0000000..80e2184
--- /dev/null
+++ b/src/main/java/fi/trustnet/browserextension/responses/LogoutResponse.java
@@ -0,0 +1,16 @@
+package fi.trustnet.browserextension.responses;
+
+public class LogoutResponse {
+ public LogoutResponse() {
+ }
+
+ private boolean loggedout;
+
+ public boolean isLoggedout() {
+ return loggedout;
+ }
+
+ public void setLoggedout(boolean loggedout) {
+ this.loggedout = loggedout;
+ }
+}
diff --git a/src/main/java/fi/trustnet/browserextension/responses/Response.java b/src/main/java/fi/trustnet/browserextension/responses/Response.java
new file mode 100644
index 0000000..6823bb5
--- /dev/null
+++ b/src/main/java/fi/trustnet/browserextension/responses/Response.java
@@ -0,0 +1,37 @@
+package fi.trustnet.browserextension.responses;
+
+
+import com.fasterxml.jackson.annotation.JsonIgnore;
+import com.fasterxml.jackson.annotation.JsonInclude;
+
+@JsonInclude(JsonInclude.Include.NON_NULL)
+public class Response {
+ private String status;
+ Object value;
+
+ public Response() {
+ }
+
+ public Response(String status, Object value) {
+ this.status = status;
+ this.value = value;
+ }
+
+ public String getStatus() {
+ return status;
+ }
+
+ public void setStatus(String status) {
+ this.status = status;
+ }
+
+ public Object getValue() {
+ return value;
+ }
+
+ public void setValue(Object value) {
+ this.value = value;
+ }
+
+
+}
diff --git a/src/main/java/fi/trustnet/browserextension/responses/SignatureResult.java b/src/main/java/fi/trustnet/browserextension/responses/SignatureResult.java
new file mode 100644
index 0000000..a303afa
--- /dev/null
+++ b/src/main/java/fi/trustnet/browserextension/responses/SignatureResult.java
@@ -0,0 +1,54 @@
+package fi.trustnet.browserextension.responses;
+
+public class SignatureResult {
+ private String dataToSign;
+ private String wallet;
+ private String signature;
+ private String verkey;
+ private String did;
+
+ public SignatureResult() {
+ }
+
+ public String getSignature() {
+ return signature;
+ }
+
+ public void setSignature(String signature) {
+ this.signature = signature;
+ }
+
+ public String getDataToSign() {
+ return dataToSign;
+ }
+
+ public void setDataToSign(String dataToSign) {
+ this.dataToSign = dataToSign;
+ }
+
+ public String getWallet() {
+ return wallet;
+ }
+
+ public void setWallet(String wallet) {
+ this.wallet = wallet;
+ }
+
+ public String getVerkey() {
+ return verkey;
+ }
+
+ public void setVerkey(String verkey) {
+ this.verkey = verkey;
+ }
+
+ public String getDid() {
+ return did;
+ }
+
+ public void setDid(String did) {
+ this.did = did;
+ }
+
+
+}
diff --git a/src/main/java/fi/trustnet/browserextension/responses/SignatureVerificationResult.java b/src/main/java/fi/trustnet/browserextension/responses/SignatureVerificationResult.java
new file mode 100644
index 0000000..c004e9d
--- /dev/null
+++ b/src/main/java/fi/trustnet/browserextension/responses/SignatureVerificationResult.java
@@ -0,0 +1,44 @@
+package fi.trustnet.browserextension.responses;
+
+public class SignatureVerificationResult {
+ private boolean verified;
+ private String message;
+ private String signature;
+ private String did;
+
+ public SignatureVerificationResult() {
+ }
+
+ public boolean isVerified() {
+ return verified;
+ }
+
+ public void setVerified(boolean verified) {
+ this.verified = verified;
+ }
+
+ public String getMessage() {
+ return message;
+ }
+
+ public void setMessage(String message) {
+ this.message = message;
+ }
+
+ public String getSignature() {
+ return signature;
+ }
+
+ public void setSignature(String signature) {
+ this.signature = signature;
+ }
+
+ public String getDid() {
+ return did;
+ }
+
+ public void setDid(String did) {
+ this.did = did;
+ }
+
+}
diff --git a/src/main/java/fi/trustnet/browserextension/responses/WalletResult.java b/src/main/java/fi/trustnet/browserextension/responses/WalletResult.java
new file mode 100644
index 0000000..19d9552
--- /dev/null
+++ b/src/main/java/fi/trustnet/browserextension/responses/WalletResult.java
@@ -0,0 +1,25 @@
+package fi.trustnet.browserextension.responses;
+
+public class WalletResult {
+ private String walletname;
+ private String operation;
+
+ public WalletResult() {
+ }
+
+ public String getWalletname() {
+ return walletname;
+ }
+
+ public void setWalletname(String walletname) {
+ this.walletname = walletname;
+ }
+
+ public String getOperation() {
+ return operation;
+ }
+
+ public void setOperation(String operation) {
+ this.operation = operation;
+ }
+}
diff --git a/src/main/java/fi/trustnet/browserextension/user/Logger.java b/src/main/java/fi/trustnet/browserextension/user/Logger.java
new file mode 100644
index 0000000..4b67b5e
--- /dev/null
+++ b/src/main/java/fi/trustnet/browserextension/user/Logger.java
@@ -0,0 +1,16 @@
+package fi.trustnet.browserextension.user;
+
+import java.io.FileWriter;
+
+public class Logger {
+ public static void writeToLog(String entry) {
+ try {
+ FileWriter fw = new FileWriter("exceptions.txt", true);
+ fw.write(entry + "\n");
+ fw.flush();
+ fw.close();
+ }
+ catch (Exception e) {
+ }
+ }
+}
diff --git a/src/main/java/fi/trustnet/browserextension/user/Token.java b/src/main/java/fi/trustnet/browserextension/user/Token.java
new file mode 100644
index 0000000..8cc1820
--- /dev/null
+++ b/src/main/java/fi/trustnet/browserextension/user/Token.java
@@ -0,0 +1,27 @@
+package fi.trustnet.browserextension.user;
+
+public class Token {
+
+ private String token;
+ private String username;
+
+ public Token() {
+
+ }
+
+ public String getToken() {
+ return token;
+ }
+
+ public void setToken(String token) {
+ this.token = token;
+ }
+
+ public String getUsername() {
+ return username;
+ }
+
+ public void setUsername(String username) {
+ this.username = username;
+ }
+}
diff --git a/src/main/java/fi/trustnet/browserextension/user/TokenStore.java b/src/main/java/fi/trustnet/browserextension/user/TokenStore.java
new file mode 100644
index 0000000..9630ba9
--- /dev/null
+++ b/src/main/java/fi/trustnet/browserextension/user/TokenStore.java
@@ -0,0 +1,98 @@
+package fi.trustnet.browserextension.user;
+
+import java.sql.*;
+
+import static fi.trustnet.browserextension.Configuration.TOKEN_DB_FILE;
+
+public class TokenStore {
+ private static final String TABLENAME = "tokens";
+
+ private static Connection connect() {
+
+ Connection conn = null;
+ try {
+ Class.forName("org.sqlite.JDBC");
+ String url = "jdbc:sqlite:" + TOKEN_DB_FILE;
+
+ try {
+ conn = DriverManager.getConnection(url);
+ } catch (SQLException e) {
+ //System.out.println(e.getMessage());
+ }
+ } catch (Exception e) {
+
+ }
+ return conn;
+ }
+
+ private static void createTables() {
+
+ String sql = "CREATE TABLE IF NOT EXISTS " + TABLENAME + " (\n"
+ + " token text PRIMARY KEY,\n"
+ + " username text NOT NULL\n"
+ + ");";
+
+ try (Connection conn = connect();
+ Statement stmt = conn.createStatement()) {
+ // create a new table
+ stmt.execute(sql);
+ } catch (SQLException e) {
+ Logger.writeToLog(e.getMessage());
+ }
+ }
+
+
+
+
+ public static void initTokenDb() {
+ createTables();
+ }
+
+ public static void storeNewToken(Token token) {
+ String sql = "INSERT INTO " + TABLENAME +" (token,username) VALUES(?,?)";
+
+ try (Connection conn = connect();
+ PreparedStatement pstmt = conn.prepareStatement(sql)) {
+ pstmt.setString(1, token.getToken());
+ pstmt.setString(2, token.getUsername());
+ pstmt.executeUpdate();
+ } catch (SQLException e) {
+ Logger.writeToLog(e.getMessage());
+ }
+ }
+
+ public static Token findTokenByTokenId(String tokenId) {
+ String sql = "SELECT * FROM " + TABLENAME + " WHERE token=\"" + tokenId +"\"";
+ Token token = null;
+ try (Connection conn = connect();
+ Statement stmt = conn.createStatement();
+ ResultSet rs = stmt.executeQuery(sql)){
+
+ if(rs.next()) {
+ token = new Token();
+ token.setToken(rs.getString("token"));
+ token.setUsername(rs.getString("username"));
+ }
+
+ } catch (SQLException e) {
+ Logger.writeToLog(e.getMessage());
+ }
+ return token;
+ }
+
+ public static void removeToken(String tokenId) {
+ String sql = "DELETE FROM " + TABLENAME + " WHERE token=\"" +tokenId + "\"";
+ try (Connection conn = connect();
+ PreparedStatement preparedStatement = conn.prepareStatement(sql)) {
+
+ preparedStatement.executeUpdate();
+ }
+
+ catch (SQLException e) {
+ Logger.writeToLog(e.getMessage());
+ }
+ }
+
+
+}
+
diff --git a/src/main/java/fi/trustnet/browserextension/user/UserAccount.java b/src/main/java/fi/trustnet/browserextension/user/UserAccount.java
new file mode 100644
index 0000000..5af4c30
--- /dev/null
+++ b/src/main/java/fi/trustnet/browserextension/user/UserAccount.java
@@ -0,0 +1,34 @@
+package fi.trustnet.browserextension.user;
+
+public class UserAccount {
+ private String username;
+ private String password;
+ private String walletname;
+
+ public UserAccount() {
+ }
+
+ public String getUsername() {
+ return username;
+ }
+
+ public void setUsername(String username) {
+ this.username = username;
+ }
+
+ public String getPassword() {
+ return password;
+ }
+
+ public void setPassword(String password) {
+ this.password = password;
+ }
+
+ public String getWalletname() {
+ return walletname;
+ }
+
+ public void setWalletname(String walletname) {
+ this.walletname = walletname;
+ }
+}
diff --git a/src/main/java/fi/trustnet/browserextension/user/UserStore.java b/src/main/java/fi/trustnet/browserextension/user/UserStore.java
new file mode 100644
index 0000000..3355b7f
--- /dev/null
+++ b/src/main/java/fi/trustnet/browserextension/user/UserStore.java
@@ -0,0 +1,136 @@
+package fi.trustnet.browserextension.user;
+
+import org.mindrot.jbcrypt.BCrypt;
+
+import javax.jws.soap.SOAPBinding;
+import java.sql.*;
+
+import static fi.trustnet.browserextension.Configuration.USER_DB_FILE;
+
+public class UserStore {
+ private static final String TABLENAME = "users";
+ private static int workload = 10;
+
+
+ private static Connection connect() {
+ // SQLite connection string
+ Connection conn = null;
+ try {
+ Class.forName("org.sqlite.JDBC");
+ String url = "jdbc:sqlite:" + USER_DB_FILE;
+
+ try {
+ conn = DriverManager.getConnection(url);
+ } catch (SQLException e) {
+ Logger.writeToLog(e.getMessage());
+ }
+ } catch (Exception e) {
+
+ }
+ return conn;
+ }
+
+ private static void createTables() {
+
+ String sql = "CREATE TABLE IF NOT EXISTS " + TABLENAME + " (\n"
+ + " id integer PRIMARY KEY,\n"
+ + " username text UNIQUE NOT NULL,\n"
+ + " password text NOT NULL, \n"
+ + " walletname text NOT NULL \n"
+ + ");";
+
+ try (Connection conn = connect();
+ Statement stmt = conn.createStatement()) {
+ // create a new table
+ stmt.execute(sql);
+ } catch (SQLException e) {
+ Logger.writeToLog(e.getMessage()); }
+ }
+
+ public static void initUserDb() {
+ createTables();
+ }
+
+ public static void storeNewUser(UserAccount userAccount) {
+ String sql = "INSERT INTO " + TABLENAME +" (username,password, walletname) VALUES(?,?,?)";
+
+ try (Connection conn = connect();
+ PreparedStatement pstmt = conn.prepareStatement(sql)) {
+ pstmt.setString(1, userAccount.getUsername());
+ pstmt.setString(2, hashPassword(userAccount.getPassword()));
+ pstmt.setString(3, userAccount.getWalletname());
+ pstmt.executeUpdate();
+ } catch (SQLException e) {
+ Logger.writeToLog(e.getMessage()); }
+ }
+
+ public static UserAccount findUserByUsername(String name) {
+ String sql = "SELECT * FROM " + TABLENAME + " WHERE username=\"" + name +"\"";
+ UserAccount userAccount = null;
+ try (Connection conn = connect();
+ Statement stmt = conn.createStatement();
+ ResultSet rs = stmt.executeQuery(sql)){
+ if(rs.next()) {
+ userAccount = new UserAccount();
+ userAccount.setUsername(rs.getString("username"));
+ userAccount.setWalletname(rs.getString("walletname"));
+ userAccount.setPassword(rs.getString("password"));
+ }
+
+ } catch (SQLException e) {
+ Logger.writeToLog(e.getMessage()); }
+ return userAccount;
+ }
+
+ public static String getWalletNameByUsername(String username) {
+ UserAccount userAccount = findUserByUsername(username);
+ if (userAccount != null) {
+ return userAccount.getWalletname();
+ }
+ else {
+ return null;
+ }
+ }
+
+ public static void deleteUser(String username) {
+ String sql = "DELETE FROM " + TABLENAME + " WHERE username=\"" +username + "\"";
+ try (Connection conn = connect();
+ PreparedStatement preparedStatement = conn.prepareStatement(sql)) {
+
+ preparedStatement.executeUpdate();
+ }
+
+ catch (SQLException e) {
+ Logger.writeToLog(e.getMessage()); }
+
+ }
+ public static boolean login(String username, String password) {
+ UserAccount userAccount = findUserByUsername(username);
+ if (checkPassword(password, userAccount.getPassword())) {
+ return true;
+ }
+ else {
+ return false;
+ }
+ }
+
+ private static String hashPassword(String password_plaintext) {
+ String salt = BCrypt.gensalt(workload);
+ String hashed_password = BCrypt.hashpw(password_plaintext, salt);
+
+ return(hashed_password);
+ }
+
+ private static boolean checkPassword(String password_plaintext, String stored_hash) {
+ boolean password_verified = false;
+
+ if(null == stored_hash || !stored_hash.startsWith("$2a$"))
+ //throw new java.lang.IllegalArgumentException("Invalid hash provided for comparison");
+ Logger.writeToLog("checkPassword : Invalid hash provided for comparison");
+
+ password_verified = BCrypt.checkpw(password_plaintext, stored_hash);
+
+ return(password_verified);
+ }
+
+}
diff --git a/src/test/java/fi/trustnet/browserextension/AppTest.java b/src/test/java/fi/trustnet/browserextension/AppTest.java
new file mode 100644
index 0000000..a9162bd
--- /dev/null
+++ b/src/test/java/fi/trustnet/browserextension/AppTest.java
@@ -0,0 +1,20 @@
+package fi.trustnet.browserextension;
+
+import static org.junit.Assert.assertTrue;
+
+import org.junit.Test;
+
+/**
+ * Unit test for simple App.
+ */
+public class AppTest
+{
+ /**
+ * Rigorous Test :-)
+ */
+ @Test
+ public void shouldAnswerWithTrue()
+ {
+ assertTrue( true );
+ }
+}