aboutsummaryrefslogtreecommitdiff
path: root/pdf-as-lib/src/main/java/at/gv/egiz/sl20/utils
diff options
context:
space:
mode:
authorThomas Lenz <thomas.lenz@egiz.gv.at>2018-07-09 10:11:25 +0200
committerThomas Lenz <thomas.lenz@egiz.gv.at>2018-07-09 10:11:25 +0200
commit9acf3c2e8aca9016daf76785747d838cdc5b0330 (patch)
treef97d392a8eff4906c961128e231926a76829a4c8 /pdf-as-lib/src/main/java/at/gv/egiz/sl20/utils
parent797634c687c6f44d314e4baa3fed220d142eed73 (diff)
downloadpdf-as-4-9acf3c2e8aca9016daf76785747d838cdc5b0330.tar.gz
pdf-as-4-9acf3c2e8aca9016daf76785747d838cdc5b0330.tar.bz2
pdf-as-4-9acf3c2e8aca9016daf76785747d838cdc5b0330.zip
add SL20 connecter-backend in a first beta version (getCertificate looks good, create signature is untested)
Diffstat (limited to 'pdf-as-lib/src/main/java/at/gv/egiz/sl20/utils')
-rw-r--r--pdf-as-lib/src/main/java/at/gv/egiz/sl20/utils/IJOSETools.java54
-rw-r--r--pdf-as-lib/src/main/java/at/gv/egiz/sl20/utils/SL20Constants.java232
-rw-r--r--pdf-as-lib/src/main/java/at/gv/egiz/sl20/utils/SL20JSONBuilderUtils.java604
-rw-r--r--pdf-as-lib/src/main/java/at/gv/egiz/sl20/utils/SL20JSONExtractorUtils.java422
4 files changed, 1312 insertions, 0 deletions
diff --git a/pdf-as-lib/src/main/java/at/gv/egiz/sl20/utils/IJOSETools.java b/pdf-as-lib/src/main/java/at/gv/egiz/sl20/utils/IJOSETools.java
new file mode 100644
index 00000000..a0f369d8
--- /dev/null
+++ b/pdf-as-lib/src/main/java/at/gv/egiz/sl20/utils/IJOSETools.java
@@ -0,0 +1,54 @@
+package at.gv.egiz.sl20.utils;
+
+import java.security.cert.X509Certificate;
+
+import com.google.gson.JsonElement;
+
+import at.gv.egiz.sl20.data.VerificationResult;
+import at.gv.egiz.sl20.exceptions.SL20Exception;
+import at.gv.egiz.sl20.exceptions.SLCommandoBuildException;
+
+public interface IJOSETools {
+
+ /**
+ * Check if the JOSE tools are initialized
+ *
+ * @return
+ */
+ public boolean isInitialized();
+
+ /**
+ * Create a JWS signature
+ *
+ * @param payLoad Payload to sign
+ * @throws SLCommandoBuildException
+ */
+ public String createSignature(String payLoad) throws SLCommandoBuildException;
+
+ /**
+ * Validates a JWS signature
+ *
+ * @param serializedContent
+ * @return
+ * @throws SLCommandoParserException
+ * @throws SL20Exception
+ */
+ public VerificationResult validateSignature(String serializedContent) throws SL20Exception;
+
+ /**
+ * Get the encryption certificate for SL2.0 End-to-End encryption
+ *
+ * @return
+ */
+ public X509Certificate getEncryptionCertificate();
+
+ /**
+ * Decrypt a serialized JWE token
+ *
+ * @param compactSerialization Serialized JWE token
+ * @return decrypted payload
+ * @throws SL20Exception
+ */
+ public JsonElement decryptPayload(String compactSerialization) throws SL20Exception;
+
+}
diff --git a/pdf-as-lib/src/main/java/at/gv/egiz/sl20/utils/SL20Constants.java b/pdf-as-lib/src/main/java/at/gv/egiz/sl20/utils/SL20Constants.java
new file mode 100644
index 00000000..59c3079d
--- /dev/null
+++ b/pdf-as-lib/src/main/java/at/gv/egiz/sl20/utils/SL20Constants.java
@@ -0,0 +1,232 @@
+package at.gv.egiz.sl20.utils;
+
+import java.util.Arrays;
+import java.util.List;
+
+import org.jose4j.jwe.ContentEncryptionAlgorithmIdentifiers;
+import org.jose4j.jwe.KeyManagementAlgorithmIdentifiers;
+import org.jose4j.jws.AlgorithmIdentifiers;
+
+public class SL20Constants {
+ public static final int CURRENT_SL20_VERSION = 10;
+
+ //http binding parameters
+ public static final String PARAM_SL20_REQ_COMMAND_PARAM = "slcommand";
+ public static final String PARAM_SL20_REQ_COMMAND_PARAM_OLD = "sl2command";
+
+ public static final String PARAM_SL20_REQ_ICP_RETURN_URL_PARAM = "slIPCReturnUrl";
+ public static final String PARAM_SL20_REQ_TRANSACTIONID = "slTransactionID";
+
+ public static final String HTTP_HEADER_SL20_CLIENT_TYPE = "SL2ClientType";
+ public static final String HTTP_HEADER_SL20_VDA_TYPE = "X-MOA-VDA";
+ public static final String HTTP_HEADER_VALUE_NATIVE = "nativeApp";
+
+
+ //*******************************************************************************************
+ //JSON signing and encryption headers
+ public static final String JSON_ALGORITHM = "alg";
+ public static final String JSON_CONTENTTYPE = "cty";
+ public static final String JSON_X509_CERTIFICATE = "x5c";
+ public static final String JSON_X509_FINGERPRINT = "x5t#S256";
+ public static final String JSON_ENCRYPTION_PAYLOAD = "enc";
+
+ public static final String JSON_ALGORITHM_SIGNING_RS256 = AlgorithmIdentifiers.RSA_USING_SHA256;
+ public static final String JSON_ALGORITHM_SIGNING_RS512 = AlgorithmIdentifiers.RSA_USING_SHA512;
+ public static final String JSON_ALGORITHM_SIGNING_ES256 = AlgorithmIdentifiers.ECDSA_USING_P256_CURVE_AND_SHA256;
+ public static final String JSON_ALGORITHM_SIGNING_ES512 = AlgorithmIdentifiers.ECDSA_USING_P521_CURVE_AND_SHA512;
+ public static final String JSON_ALGORITHM_SIGNING_PS256 = AlgorithmIdentifiers.RSA_PSS_USING_SHA256;
+ public static final String JSON_ALGORITHM_SIGNING_PS512 = AlgorithmIdentifiers.RSA_PSS_USING_SHA512;
+
+ public static final List<String> SL20_ALGORITHM_WHITELIST_SIGNING = Arrays.asList(
+ JSON_ALGORITHM_SIGNING_RS256,
+ JSON_ALGORITHM_SIGNING_RS512,
+ JSON_ALGORITHM_SIGNING_ES256,
+ JSON_ALGORITHM_SIGNING_ES512,
+ JSON_ALGORITHM_SIGNING_PS256,
+ JSON_ALGORITHM_SIGNING_PS512
+ );
+
+ public static final String JSON_ALGORITHM_ENC_KEY_RSAOAEP = KeyManagementAlgorithmIdentifiers.RSA_OAEP;
+ public static final String JSON_ALGORITHM_ENC_KEY_RSAOAEP256 = KeyManagementAlgorithmIdentifiers.RSA_OAEP_256;
+
+ public static final List<String> SL20_ALGORITHM_WHITELIST_KEYENCRYPTION = Arrays.asList(
+ JSON_ALGORITHM_ENC_KEY_RSAOAEP,
+ JSON_ALGORITHM_ENC_KEY_RSAOAEP256
+ );
+
+ public static final String JSON_ALGORITHM_ENC_PAYLOAD_A128CBCHS256 = ContentEncryptionAlgorithmIdentifiers.AES_128_CBC_HMAC_SHA_256;
+ public static final String JSON_ALGORITHM_ENC_PAYLOAD_A256CBCHS512 = ContentEncryptionAlgorithmIdentifiers.AES_256_CBC_HMAC_SHA_512;
+ public static final String JSON_ALGORITHM_ENC_PAYLOAD_A128GCM = ContentEncryptionAlgorithmIdentifiers.AES_128_GCM;
+ public static final String JSON_ALGORITHM_ENC_PAYLOAD_A256GCM = ContentEncryptionAlgorithmIdentifiers.AES_256_GCM;
+
+ public static final List<String> SL20_ALGORITHM_WHITELIST_ENCRYPTION = Arrays.asList(
+ JSON_ALGORITHM_ENC_PAYLOAD_A128CBCHS256,
+ JSON_ALGORITHM_ENC_PAYLOAD_A256CBCHS512,
+ JSON_ALGORITHM_ENC_PAYLOAD_A128GCM,
+ JSON_ALGORITHM_ENC_PAYLOAD_A256GCM
+ );
+
+
+ //*********************************************************************************************
+ //Object identifier for generic transport container
+ public static final String SL20_CONTENTTYPE_SIGNED_COMMAND ="application/sl2.0;command";
+ public static final String SL20_CONTENTTYPE_ENCRYPTED_RESULT ="application/sl2.0;result";
+
+ public static final String SL20_VERSION = "v";
+ public static final String SL20_REQID = "reqID";
+ public static final String SL20_RESPID = "respID";
+ public static final String SL20_INRESPTO = "inResponseTo";
+ public static final String SL20_TRANSACTIONID = "transactionID";
+ public static final String SL20_PAYLOAD = "payload";
+ public static final String SL20_SIGNEDPAYLOAD = "signedPayload";
+
+ //Generic Object identifier for commands
+ public static final String SL20_COMMAND_CONTAINER_NAME = "name";
+ public static final String SL20_COMMAND_CONTAINER_PARAMS = "params";
+ public static final String SL20_COMMAND_CONTAINER_RESULT = "result";
+ public static final String SL20_COMMAND_CONTAINER_ENCRYPTEDRESULT = "encryptedResult";
+
+ //COMMAND Object identifier
+ public static final String SL20_COMMAND_IDENTIFIER_REDIRECT = "redirect";
+ public static final String SL20_COMMAND_IDENTIFIER_CALL = "call";
+ public static final String SL20_COMMAND_IDENTIFIER_ERROR = "error";
+ public static final String SL20_COMMAND_IDENTIFIER_QUALIFIEDEID = "qualifiedeID";
+ //public static final String SL20_COMMAND_IDENTIFIER_QUALIFIEDSIG = "qualifiedSig";
+
+ public static final String SL20_COMMAND_IDENTIFIER_GETCERTIFICATE = "getCertificate";
+ public static final String SL20_COMMAND_IDENTIFIER_CREATE_SIG_CADES = "createCAdES";
+
+
+ public static final String SL20_COMMAND_IDENTIFIER_BINDING_CREATE_KEY = "createBindingKey";
+ public static final String SL20_COMMAND_IDENTIFIER_BINDING_STORE_CERT = "storeBindingCert";
+
+ public static final String SL20_COMMAND_IDENTIFIER_AUTH_IDANDPASSWORD = "idAndPassword";
+ public static final String SL20_COMMAND_IDENTIFIER_AUTH_JWSTOKENFACTOR = "jwsTokenAuth";
+ public static final String SL20_COMMAND_IDENTIFIER_AUTH_QRCODEFACTOR = "qrCodeFactor";
+
+ //*****COMMAND parameter identifier******
+ //general Identifier
+ public static final String SL20_COMMAND_PARAM_GENERAL_REQPARAMETER_VALUE = "value";
+ public static final String SL20_COMMAND_PARAM_GENERAL_REQPARAMETER_KEY = "key";
+ public static final String SL20_COMMAND_PARAM_GENERAL_DATAURL = "dataUrl";
+ public static final String SL20_COMMAND_PARAM_GENERAL_RESPONSEENCRYPTIONCERTIFICATE = "x5cEnc";
+ public static final String SL20_COMMAND_PARAM_GENERAL_RESPONSEENCRYPTIONJWK = "jwkEnc";
+
+ //Redirect command
+ public static final String SL20_COMMAND_PARAM_GENERAL_REDIRECT_URL = "url";
+ public static final String SL20_COMMAND_PARAM_GENERAL_REDIRECT_COMMAND = "command";
+ public static final String SL20_COMMAND_PARAM_GENERAL_REDIRECT_SIGNEDCOMMAND = "signedCommand";
+ public static final String SL20_COMMAND_PARAM_GENERAL_REDIRECT_IPCREDIRECT = "IPCRedirect";
+
+ //Call command
+ public static final String SL20_COMMAND_PARAM_GENERAL_CALL_URL = SL20_COMMAND_PARAM_GENERAL_REDIRECT_URL;
+ public static final String SL20_COMMAND_PARAM_GENERAL_CALL_METHOD = "method";
+ public static final String SL20_COMMAND_PARAM_GENERAL_CALL_METHOD_GET = "get";
+ public static final String SL20_COMMAND_PARAM_GENERAL_CALL_METHOD_POST = "post";
+ public static final String SL20_COMMAND_PARAM_GENERAL_CALL_INCLUDETRANSACTIONID = "includeTransactionID";
+ public static final String SL20_COMMAND_PARAM_GENERAL_CALL_REQPARAMETER = "reqParams";
+
+ //error command
+ public static final String SL20_COMMAND_PARAM_GENERAL_RESPONSE_ERRORCODE = "errorCode";
+ public static final String SL20_COMMAND_PARAM_GENERAL_RESPONSE_ERRORMESSAGE = "errorMessage";
+
+ //qualified eID command
+ public static final String SL20_COMMAND_PARAM_EID_AUTHBLOCKID = "authBlockTemplateID";
+ public static final String SL20_COMMAND_PARAM_EID_DATAURL = SL20_COMMAND_PARAM_GENERAL_DATAURL;
+ public static final String SL20_COMMAND_PARAM_EID_ATTRIBUTES = "attributes";
+ public static final String SL20_COMMAND_PARAM_EID_ATTRIBUTES_MANDATEREFVALUE = "MANDATE-REFERENCE-VALUE";
+ public static final String SL20_COMMAND_PARAM_EID_ATTRIBUTES_SPUNIQUEID = "SP-UNIQUEID";
+ public static final String SL20_COMMAND_PARAM_EID_ATTRIBUTES_SPFRIENDLYNAME = "SP-FRIENDLYNAME";
+ public static final String SL20_COMMAND_PARAM_EID_ATTRIBUTES_SPCOUNTRYCODE = "SP-COUNTRYCODE";
+ public static final String SL20_COMMAND_PARAM_EID_X5CENC = SL20_COMMAND_PARAM_GENERAL_RESPONSEENCRYPTIONCERTIFICATE;
+ public static final String SL20_COMMAND_PARAM_EID_JWKCENC = SL20_COMMAND_PARAM_GENERAL_RESPONSEENCRYPTIONJWK;
+ public static final String SL20_COMMAND_PARAM_EID_RESULT_IDL = "EID-IDENTITY-LINK";
+ public static final String SL20_COMMAND_PARAM_EID_RESULT_AUTHBLOCK = "EID-AUTH-BLOCK";
+ public static final String SL20_COMMAND_PARAM_EID_RESULT_CCSURL = "EID-CCS-URL";
+ public static final String SL20_COMMAND_PARAM_EID_RESULT_LOA = "EID-CITIZEN-QAA-LEVEL";
+
+ //qualified Signature comamnd
+// public static final String SL20_COMMAND_PARAM_QUALSIG_DATAURL = SL20_COMMAND_PARAM_GENERAL_DATAURL;
+// public static final String SL20_COMMAND_PARAM_QUALSIG_X5CENC = SL20_COMMAND_PARAM_GENERAL_RESPONSEENCRYPTIONCERTIFICATE;
+
+
+ //getCertificate
+ public static final String SL20_COMMAND_PARAM_GETCERTIFICATE_KEYID = "keyId";
+ public static final String SL20_COMMAND_PARAM_GETCERTIFICATE_DATAURL = SL20_COMMAND_PARAM_GENERAL_DATAURL;
+ public static final String SL20_COMMAND_PARAM_GETCERTIFICATE_X5CENC = SL20_COMMAND_PARAM_GENERAL_RESPONSEENCRYPTIONCERTIFICATE;
+ public static final String SL20_COMMAND_PARAM_GETCERTIFICATE_JWKCENC = SL20_COMMAND_PARAM_GENERAL_RESPONSEENCRYPTIONJWK;
+ public static final String SL20_COMMAND_PARAM_GETCERTIFICATE_RESULT_CERTIFICATE = "x5c";
+
+ //createCAdES Signture
+ public static final String SL20_COMMAND_PARAM_CREATE_SIG_CADES_KEYID = "keyId";
+ public static final String SL20_COMMAND_PARAM_CREATE_SIG_CADES_CONTENT = "content";
+ public static final String SL20_COMMAND_PARAM_CREATE_SIG_CADES_MIMETYPE = "mimeType";
+ public static final String SL20_COMMAND_PARAM_CREATE_SIG_CADES_PADES_COMBATIBILTY = "padesComatibility";
+ public static final String SL20_COMMAND_PARAM_CREATE_SIG_CADES_EXCLUDEBYTERANGE = "excludedByteRange";
+ public static final String SL20_COMMAND_PARAM_CREATE_SIG_CADES_CADESLEVEL = "cadesLevel";
+ public static final String SL20_COMMAND_PARAM_CREATE_SIG_CADES_DATAURL = SL20_COMMAND_PARAM_GENERAL_DATAURL;
+ public static final String SL20_COMMAND_PARAM_CREATE_SIG_CADES_X5CENC = SL20_COMMAND_PARAM_GENERAL_RESPONSEENCRYPTIONCERTIFICATE;
+ public static final String SL20_COMMAND_PARAM_CREATE_SIG_CADES_JWKCENC = SL20_COMMAND_PARAM_GENERAL_RESPONSEENCRYPTIONJWK;
+ public static final String SL20_COMMAND_PARAM_CREATE_SIG_CADES_RESULT_SIGNATURE = "signature";
+
+ public static final String SL20_COMMAND_PARAM_CREATE_SIG_CADES_CADESLEVEL_BASIC = "cAdES";
+ public static final String SL20_COMMAND_PARAM_CREATE_SIG_CADES_CADESLEVEL_T = "cAdES-T";
+ public static final String SL20_COMMAND_PARAM_CREATE_SIG_CADES_CADESLEVEL_C = "cAdES-C";
+ public static final String SL20_COMMAND_PARAM_CREATE_SIG_CADES_CADESLEVEL_X = "cAdES-X";
+ public static final String SL20_COMMAND_PARAM_CREATE_SIG_CADES_CADESLEVEL_XL = "cAdES-X-L";
+ public static final String SL20_COMMAND_PARAM_CREATE_SIG_CADES_CADESLEVEL_A = "cAdES-A";
+
+
+
+ //create binding key command
+ public static final String SL20_COMMAND_PARAM_BINDING_CREATE_KONTOID = "kontoID";
+ public static final String SL20_COMMAND_PARAM_BINDING_CREATE_SN = "SN";
+ public static final String SL20_COMMAND_PARAM_BINDING_CREATE_KEYLENGTH = "keyLength";
+ public static final String SL20_COMMAND_PARAM_BINDING_CREATE_KEYALG = "keyAlg";
+ public static final String SL20_COMMAND_PARAM_BINDING_CREATE_POLICIES = "policies";
+ public static final String SL20_COMMAND_PARAM_BINDING_CREATE_DATAURL = SL20_COMMAND_PARAM_GENERAL_DATAURL;
+ public static final String SL20_COMMAND_PARAM_BINDING_CREATE_X5CVDATRUST = "x5cVdaTrust";
+ public static final String SL20_COMMAND_PARAM_BINDING_CREATE_REQUESTUSERPASSWORD = "reqUserPassword";
+ public static final String SL20_COMMAND_PARAM_BINDING_CREATE_X5CENC = SL20_COMMAND_PARAM_GENERAL_RESPONSEENCRYPTIONCERTIFICATE;
+
+ public static final String SL20_COMMAND_PARAM_BINDING_CREATE_KEYALG_RSA = "RSA";
+ public static final String SL20_COMMAND_PARAM_BINDING_CREATE_KEYALG_SECPR256R1 = "secp256r1";
+
+ public static final String SL20_COMMAND_PARAM_BINDING_CREATE_POLICIES_LIFETIME = "lifeTime";
+ public static final String SL20_COMMAND_PARAM_BINDING_CREATE_POLICIES_USESECUREELEMENT = "useSecureElement";
+ public static final String SL20_COMMAND_PARAM_BINDING_CREATE_POLICIES_KEYTIMEOUT = "keyTimeout";
+ public static final String SL20_COMMAND_PARAM_BINDING_CREATE_POLICIES_NEEDUSERAUTH = "needUserAuth";
+
+ public static final String SL20_COMMAND_PARAM_BINDING_CREATE_RESULT_APPID = "appID";
+ public static final String SL20_COMMAND_PARAM_BINDING_CREATE_RESULT_CSR = "csr";
+ public static final String SL20_COMMAND_PARAM_BINDING_CREATE_RESULT_KEYATTESTATIONZERTIFICATE = "attCert";
+ public static final String SL20_COMMAND_PARAM_BINDING_CREATE_RESULT_USERPASSWORD = "encodedPass";
+
+
+ //store binding certificate command
+ public static final String SL20_COMMAND_PARAM_BINDING_STORE_CERTIFICATE = "x5c";
+ public static final String SL20_COMMAND_PARAM_BINDING_STORE_DATAURL = SL20_COMMAND_PARAM_GENERAL_DATAURL;
+ public static final String SL20_COMMAND_PARAM_BINDING_STORE_RESULT_SUCESS = "success";
+ public static final String SL20_COMMAND_PARAM_BINDING_STORE_RESULT_SUCESS_VALUE = "OK";
+
+ // Username and password authentication
+ public static final String SL20_COMMAND_PARAM_AUTH_IDANDPASSWORD_KEYALG = "keyAlg";
+ public static final String SL20_COMMAND_PARAM_AUTH_IDANDPASSWORD_KEYALG_VALUE_PLAIN = "plain";
+ public static final String SL20_COMMAND_PARAM_AUTH_IDANDPASSWORD_KEYALG_VALUE_PBKDF2 = "PBKDF2";
+ public static final String SL20_COMMAND_PARAM_AUTH_IDANDPASSWORD_DATAURL = SL20_COMMAND_PARAM_GENERAL_DATAURL;
+ public static final String SL20_COMMAND_PARAM_AUTH_IDANDPASSWORD_X5CENC = SL20_COMMAND_PARAM_GENERAL_RESPONSEENCRYPTIONCERTIFICATE;
+ public static final String SL20_COMMAND_PARAM_AUTH_IDANDPASSWORD_RESULT_KONTOID = SL20_COMMAND_PARAM_BINDING_CREATE_KONTOID;
+ public static final String SL20_COMMAND_PARAM_AUTH_IDANDPASSWORD_RESULT_USERPASSWORD = SL20_COMMAND_PARAM_BINDING_CREATE_RESULT_USERPASSWORD;
+
+ //JWS Token authentication
+ public static final String SL20_COMMAND_PARAM_AUTH_JWSTOKEN_NONCE = "nonce";
+ public static final String SL20_COMMAND_PARAM_AUTH_JWSTOKEN_DISPLAYDATA = "displayData";
+ public static final String SL20_COMMAND_PARAM_AUTH_JWSTOKEN_DISPLAYURL = "displayUrl";
+ public static final String SL20_COMMAND_PARAM_AUTH_JWSTOKEN_DATAURL = SL20_COMMAND_PARAM_GENERAL_DATAURL;
+ public static final String SL20_COMMAND_PARAM_AUTH_JWSTOKEN_RESULT_NONCE = SL20_COMMAND_PARAM_AUTH_JWSTOKEN_NONCE;
+
+ //QR-Code authentication
+ public static final String SL20_COMMAND_PARAM_AUTH_QRCODE_QRCODE = "qrCode";
+ public static final String SL20_COMMAND_PARAM_AUTH_QRCODE_DATAURL = SL20_COMMAND_PARAM_GENERAL_DATAURL;
+
+}
diff --git a/pdf-as-lib/src/main/java/at/gv/egiz/sl20/utils/SL20JSONBuilderUtils.java b/pdf-as-lib/src/main/java/at/gv/egiz/sl20/utils/SL20JSONBuilderUtils.java
new file mode 100644
index 00000000..40edb74b
--- /dev/null
+++ b/pdf-as-lib/src/main/java/at/gv/egiz/sl20/utils/SL20JSONBuilderUtils.java
@@ -0,0 +1,604 @@
+package at.gv.egiz.sl20.utils;
+
+import java.security.cert.CertificateEncodingException;
+import java.security.cert.X509Certificate;
+import java.util.Arrays;
+import java.util.List;
+import java.util.Map;
+import java.util.Map.Entry;
+
+import org.apache.commons.codec.binary.Base64;
+import org.bouncycastle.util.encoders.Base64Encoder;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.google.gson.JsonArray;
+import com.google.gson.JsonElement;
+import com.google.gson.JsonObject;
+
+import at.gv.egiz.sl20.exceptions.SLCommandoBuildException;
+
+public class SL20JSONBuilderUtils {
+ private static final Logger log = LoggerFactory.getLogger(SL20JSONBuilderUtils.class);
+
+ /**
+ * Create command request
+ * @param name
+ * @param params
+ * @throws SLCommandoBuildException
+ * @return
+ */
+ public static JsonObject createCommand(String name, JsonElement params) throws SLCommandoBuildException {
+ JsonObject command = new JsonObject();
+ addSingleStringElement(command, SL20Constants.SL20_COMMAND_CONTAINER_NAME, name, true);
+ addSingleJSONElement(command, SL20Constants.SL20_COMMAND_CONTAINER_PARAMS, params, true);
+ return command;
+
+ }
+
+ /**
+ * Create signed command request
+ *
+ * @param name
+ * @param params
+ * @param signer
+ * @return
+ * @throws SLCommandoBuildException
+ */
+ public static String createSignedCommand(String name, JsonElement params, IJOSETools signer) throws SLCommandoBuildException {
+ JsonObject command = new JsonObject();
+ addSingleStringElement(command, SL20Constants.SL20_COMMAND_CONTAINER_NAME, name, true);
+ addSingleJSONElement(command, SL20Constants.SL20_COMMAND_CONTAINER_PARAMS, params, true);
+ return signer.createSignature(command.toString());
+
+ }
+
+ /**
+ * Create command result
+ *
+ * @param name
+ * @param result
+ * @param encryptedResult
+ * @throws SLCommandoBuildException
+ * @return
+ */
+ public static JsonObject createCommandResponse(String name, JsonElement result, String encryptedResult) throws SLCommandoBuildException {
+ JsonObject command = new JsonObject();
+ addSingleStringElement(command, SL20Constants.SL20_COMMAND_CONTAINER_NAME, name, true);
+ addOnlyOnceOfTwo(command,
+ SL20Constants.SL20_COMMAND_CONTAINER_RESULT, SL20Constants.SL20_COMMAND_CONTAINER_ENCRYPTEDRESULT,
+ result, encryptedResult);
+ return command;
+
+ }
+
+ /**
+ * Create command result
+ *
+ * @param name
+ * @param result
+ * @param encryptedResult
+ * @throws SLCommandoBuildException
+ * @return
+ */
+ public static String createSignedCommandResponse(String name, JsonElement result, String encryptedResult, IJOSETools signer) throws SLCommandoBuildException {
+ JsonObject command = new JsonObject();
+ addSingleStringElement(command, SL20Constants.SL20_COMMAND_CONTAINER_NAME, name, true);
+ addOnlyOnceOfTwo(command,
+ SL20Constants.SL20_COMMAND_CONTAINER_RESULT, SL20Constants.SL20_COMMAND_CONTAINER_ENCRYPTEDRESULT,
+ result, encryptedResult);
+ return signer.createSignature(command.toString());
+
+ }
+
+ /**
+ * Create parameters for Redirect command
+ *
+ * @param url
+ * @param command
+ * @param signedCommand
+ * @param ipcRedirect
+ * @return
+ * @throws SLCommandoBuildException
+ */
+ public static JsonObject createRedirectCommandParameters(String url, JsonElement command, JsonElement signedCommand, Boolean ipcRedirect) throws SLCommandoBuildException{
+ JsonObject redirectReqParams = new JsonObject();
+ addOnlyOnceOfTwo(redirectReqParams,
+ SL20Constants.SL20_COMMAND_PARAM_GENERAL_REDIRECT_COMMAND, SL20Constants.SL20_COMMAND_PARAM_GENERAL_REDIRECT_SIGNEDCOMMAND,
+ command, signedCommand);
+ addSingleStringElement(redirectReqParams, SL20Constants.SL20_COMMAND_PARAM_GENERAL_REDIRECT_URL, url, false);
+ addSingleBooleanElement(redirectReqParams, SL20Constants.SL20_COMMAND_PARAM_GENERAL_REDIRECT_IPCREDIRECT, ipcRedirect, false);
+ return redirectReqParams;
+
+ }
+
+ /**
+ * Create parameters for Call command
+ *
+ * @param url
+ * @param method
+ * @param includeTransactionId
+ * @param reqParameters
+ * @return
+ * @throws SLCommandoBuildException
+ */
+ public static JsonObject createCallCommandParameters(String url, String method, Boolean includeTransactionId, Map<String, String> reqParameters) throws SLCommandoBuildException {
+ JsonObject callReqParams = new JsonObject();
+ addSingleStringElement(callReqParams, SL20Constants.SL20_COMMAND_PARAM_GENERAL_CALL_URL, url, true);
+ addSingleStringElement(callReqParams, SL20Constants.SL20_COMMAND_PARAM_GENERAL_CALL_METHOD, method, true);
+ addSingleBooleanElement(callReqParams, SL20Constants.SL20_COMMAND_PARAM_GENERAL_CALL_INCLUDETRANSACTIONID, includeTransactionId, false);
+ addArrayOfStringElements(callReqParams, SL20Constants.SL20_COMMAND_PARAM_GENERAL_CALL_REQPARAMETER, reqParameters);
+ return callReqParams;
+
+ }
+
+ /**
+ * Create result for Error command
+ *
+ * @param errorCode
+ * @param errorMsg
+ * @return
+ * @throws SLCommandoBuildException
+ */
+ public static JsonObject createErrorCommandResult(String errorCode, String errorMsg) throws SLCommandoBuildException {
+ JsonObject result = new JsonObject();
+ addSingleStringElement(result, SL20Constants.SL20_COMMAND_PARAM_GENERAL_RESPONSE_ERRORCODE, errorCode, true);
+ addSingleStringElement(result, SL20Constants.SL20_COMMAND_PARAM_GENERAL_RESPONSE_ERRORMESSAGE, errorMsg, true);
+ return result;
+
+ }
+
+
+ /**
+ * Create parameters for qualifiedeID command
+ *
+ * @param authBlockId
+ * @param dataUrl
+ * @param additionalReqParameters
+ * @param x5cEnc
+ * @return
+ * @throws CertificateEncodingException
+ * @throws SLCommandoBuildException
+ */
+ public static JsonObject createQualifiedeIDCommandParameters(String authBlockId, String dataUrl,
+ Map<String, String> additionalReqParameters, X509Certificate x5cEnc) throws CertificateEncodingException, SLCommandoBuildException {
+ JsonObject params = new JsonObject();
+ addSingleStringElement(params, SL20Constants.SL20_COMMAND_PARAM_EID_AUTHBLOCKID, authBlockId, true);
+ addSingleStringElement(params, SL20Constants.SL20_COMMAND_PARAM_EID_DATAURL, dataUrl, true);
+ addArrayOfStringElements(params, SL20Constants.SL20_COMMAND_PARAM_EID_ATTRIBUTES, additionalReqParameters);
+ addSingleCertificateElement(params, SL20Constants.SL20_COMMAND_PARAM_EID_X5CENC, x5cEnc, false);
+ return params;
+
+ }
+
+ public static JsonObject createGetCertificateCommandParameters(String keyId, String dataUrl,
+ X509Certificate x5cEnc) throws CertificateEncodingException, SLCommandoBuildException {
+ JsonObject params = new JsonObject();
+ addSingleStringElement(params, SL20Constants.SL20_COMMAND_PARAM_GETCERTIFICATE_KEYID, keyId, true);
+ addSingleStringElement(params, SL20Constants.SL20_COMMAND_PARAM_GETCERTIFICATE_DATAURL, dataUrl, true);
+ addSingleCertificateElement(params, SL20Constants.SL20_COMMAND_PARAM_GETCERTIFICATE_X5CENC, x5cEnc, false);
+ return params;
+
+ }
+
+ public static JsonObject createCreateCAdESCommandParameters(String keyId,
+ byte[] content, String mimeType, boolean padesCompatiblem, List<String> byteRanges, String cadesLevel,
+ String dataUrl, X509Certificate x5cEnc) throws CertificateEncodingException, SLCommandoBuildException {
+ JsonObject params = new JsonObject();
+ addSingleStringElement(params, SL20Constants.SL20_COMMAND_PARAM_CREATE_SIG_CADES_KEYID, keyId, true);
+ addSingleByteElement(params, SL20Constants.SL20_COMMAND_PARAM_CREATE_SIG_CADES_CONTENT, content, true);
+ addSingleStringElement(params, SL20Constants.SL20_COMMAND_PARAM_CREATE_SIG_CADES_MIMETYPE, mimeType, true);
+ addSingleBooleanElement(params, SL20Constants.SL20_COMMAND_PARAM_CREATE_SIG_CADES_PADES_COMBATIBILTY, padesCompatiblem, false);
+ addArrayOfStrings(params, SL20Constants.SL20_COMMAND_PARAM_CREATE_SIG_CADES_EXCLUDEBYTERANGE, byteRanges);
+ addSingleStringElement(params, SL20Constants.SL20_COMMAND_PARAM_CREATE_SIG_CADES_CADESLEVEL, cadesLevel, false);
+ addSingleStringElement(params, SL20Constants.SL20_COMMAND_PARAM_GETCERTIFICATE_DATAURL, dataUrl, true);
+ addSingleCertificateElement(params, SL20Constants.SL20_COMMAND_PARAM_GETCERTIFICATE_X5CENC, x5cEnc, false);
+ return params;
+
+ }
+
+ /**
+ * Create result for qualifiedeID command
+ *
+ * @param idl
+ * @param authBlock
+ * @param ccsURL
+ * @param LoA
+ * @return
+ * @throws SLCommandoBuildException
+ */
+ public static JsonObject createQualifiedeIDCommandResult(byte[] idl, byte[] authBlock, String ccsURL, String LoA) throws SLCommandoBuildException {
+ JsonObject result = new JsonObject();
+ addSingleByteElement(result, SL20Constants.SL20_COMMAND_PARAM_EID_RESULT_IDL, idl, true);
+ addSingleByteElement(result, SL20Constants.SL20_COMMAND_PARAM_EID_RESULT_AUTHBLOCK, authBlock, true);
+ addSingleStringElement(result, SL20Constants.SL20_COMMAND_PARAM_EID_RESULT_CCSURL, ccsURL, true);
+ addSingleStringElement(result, SL20Constants.SL20_COMMAND_PARAM_EID_RESULT_LOA, LoA, true);
+ return result;
+
+ }
+
+
+ /**
+ * Create Binding-Key command parameters
+ *
+ * @param kontoId
+ * @param subjectName
+ * @param keySize
+ * @param keyAlg
+ * @param policies
+ * @param dataUrl
+ * @param x5cVdaTrust
+ * @param reqUserPassword
+ * @param x5cEnc
+ * @return
+ * @throws SLCommandoBuildException
+ * @throws CertificateEncodingException
+ */
+ public static JsonObject createBindingKeyCommandParams(String kontoId, String subjectName, int keySize, String keyAlg,
+ Map<String, String> policies, String dataUrl, X509Certificate x5cVdaTrust, Boolean reqUserPassword, X509Certificate x5cEnc) throws SLCommandoBuildException, CertificateEncodingException {
+ JsonObject params = new JsonObject();
+ addSingleStringElement(params, SL20Constants.SL20_COMMAND_PARAM_BINDING_CREATE_KONTOID, kontoId, true);
+ addSingleStringElement(params, SL20Constants.SL20_COMMAND_PARAM_BINDING_CREATE_SN, subjectName, true);
+ addSingleNumberElement(params, SL20Constants.SL20_COMMAND_PARAM_BINDING_CREATE_KEYLENGTH, keySize, true);
+ addSingleStringElement(params, SL20Constants.SL20_COMMAND_PARAM_BINDING_CREATE_KEYALG, keyAlg, true);
+ addArrayOfStringElements(params, SL20Constants.SL20_COMMAND_PARAM_BINDING_CREATE_POLICIES, policies);
+ addSingleStringElement(params, SL20Constants.SL20_COMMAND_PARAM_BINDING_CREATE_DATAURL, dataUrl, true);
+ addSingleCertificateElement(params, SL20Constants.SL20_COMMAND_PARAM_BINDING_CREATE_X5CVDATRUST, x5cVdaTrust, false);
+ addSingleBooleanElement(params, SL20Constants.SL20_COMMAND_PARAM_BINDING_CREATE_REQUESTUSERPASSWORD, reqUserPassword, false);
+ addSingleCertificateElement(params, SL20Constants.SL20_COMMAND_PARAM_BINDING_CREATE_X5CENC, x5cEnc, false);
+ return params;
+
+ }
+
+ /**
+ * Create Binding-Key command result
+ *
+ * @param appId
+ * @param csr
+ * @param attCert
+ * @param password
+ * @return
+ * @throws SLCommandoBuildException
+ * @throws CertificateEncodingException
+ */
+ public static JsonObject createBindingKeyCommandResult(String appId, byte[] csr, X509Certificate attCert, byte[] password) throws SLCommandoBuildException, CertificateEncodingException {
+ JsonObject result = new JsonObject();
+ addSingleStringElement(result, SL20Constants.SL20_COMMAND_PARAM_BINDING_CREATE_RESULT_APPID, appId, true);
+ addSingleByteElement(result, SL20Constants.SL20_COMMAND_PARAM_BINDING_CREATE_RESULT_CSR, csr, true);
+ addSingleCertificateElement(result, SL20Constants.SL20_COMMAND_PARAM_BINDING_CREATE_RESULT_KEYATTESTATIONZERTIFICATE, attCert, false);
+ addSingleByteElement(result, SL20Constants.SL20_COMMAND_PARAM_BINDING_CREATE_RESULT_USERPASSWORD, password, false);
+ return result;
+
+ }
+
+ /**
+ * Create Store Binding-Certificate command parameters
+ *
+ * @param cert
+ * @param dataUrl
+ * @return
+ * @throws CertificateEncodingException
+ * @throws SLCommandoBuildException
+ */
+ public static JsonObject createStoreBindingCertCommandParams(X509Certificate cert, String dataUrl) throws CertificateEncodingException, SLCommandoBuildException {
+ JsonObject params = new JsonObject();
+ addSingleCertificateElement(params, SL20Constants.SL20_COMMAND_PARAM_BINDING_STORE_CERTIFICATE, cert, true);
+ addSingleStringElement(params, SL20Constants.SL20_COMMAND_PARAM_BINDING_STORE_DATAURL, dataUrl, true);
+ return params;
+
+ }
+
+ /**
+ * Create Store Binding-Certificate command result
+ *
+ * @return
+ * @throws SLCommandoBuildException
+ */
+ public static JsonObject createStoreBindingCertCommandSuccessResult() throws SLCommandoBuildException {
+ JsonObject result = new JsonObject();
+ addSingleStringElement(result, SL20Constants.SL20_COMMAND_PARAM_BINDING_STORE_RESULT_SUCESS,
+ SL20Constants.SL20_COMMAND_PARAM_BINDING_STORE_RESULT_SUCESS_VALUE, true);
+ return result;
+
+ }
+
+
+ /**
+ * Create idAndPassword command parameters
+ *
+ * @param keyAlg
+ * @param dataUrl
+ * @param x5cEnc
+ * @return
+ * @throws SLCommandoBuildException
+ * @throws CertificateEncodingException
+ */
+ public static JsonObject createIdAndPasswordCommandParameters(String keyAlg, String dataUrl, X509Certificate x5cEnc) throws SLCommandoBuildException, CertificateEncodingException {
+ JsonObject params = new JsonObject();
+ addSingleStringElement(params, SL20Constants.SL20_COMMAND_PARAM_AUTH_IDANDPASSWORD_KEYALG, keyAlg, true);
+ addSingleStringElement(params, SL20Constants.SL20_COMMAND_PARAM_AUTH_IDANDPASSWORD_DATAURL, dataUrl, true);
+ addSingleCertificateElement(params, SL20Constants.SL20_COMMAND_PARAM_AUTH_IDANDPASSWORD_X5CENC, x5cEnc, false);
+ return params;
+
+ }
+
+ /**
+ * Create idAndPassword command result
+ *
+ * @param kontoId
+ * @param password
+ * @return
+ * @throws SLCommandoBuildException
+ */
+ public static JsonObject createIdAndPasswordCommandResult(String kontoId, byte[] password) throws SLCommandoBuildException {
+ JsonObject result = new JsonObject();
+ addSingleStringElement(result, SL20Constants.SL20_COMMAND_PARAM_AUTH_IDANDPASSWORD_RESULT_KONTOID, kontoId, true);
+ addSingleByteElement(result, SL20Constants.SL20_COMMAND_PARAM_AUTH_IDANDPASSWORD_RESULT_USERPASSWORD, password, true);
+ return result;
+
+ }
+
+ /**
+ * Create JWS Token Authentication command
+ *
+ * @param nonce
+ * @param dataUrl
+ * @param displayData
+ * @param displayUrl
+ * @return
+ * @throws SLCommandoBuildException
+ */
+ public static JsonObject createJwsTokenAuthCommandParams(String nonce, String dataUrl, List<String> displayData, List<String> displayUrl) throws SLCommandoBuildException {
+ JsonObject params = new JsonObject();
+ addSingleStringElement(params, SL20Constants.SL20_COMMAND_PARAM_AUTH_JWSTOKEN_NONCE, nonce, true);
+ addSingleStringElement(params, SL20Constants.SL20_COMMAND_PARAM_AUTH_JWSTOKEN_DATAURL, dataUrl, true);
+ addArrayOfStrings(params, SL20Constants.SL20_COMMAND_PARAM_AUTH_JWSTOKEN_DISPLAYDATA, displayData);
+ addArrayOfStrings(params, SL20Constants.SL20_COMMAND_PARAM_AUTH_JWSTOKEN_DISPLAYURL, displayUrl);
+ return params;
+
+ }
+
+ /**
+ * Create JWS Token Authentication command result
+ *
+ * @param nonce
+ * @return
+ * @throws SLCommandoBuildException
+ */
+ public static JsonObject createJwsTokenAuthCommandResult(String nonce) throws SLCommandoBuildException {
+ JsonObject result = new JsonObject();
+ addSingleStringElement(result, SL20Constants.SL20_COMMAND_PARAM_AUTH_JWSTOKEN_RESULT_NONCE, nonce, true);
+ return result;
+
+ }
+
+
+ /**
+ * Create Generic Request Container
+ *
+ * @param reqId
+ * @param transactionId
+ * @param payLoad
+ * @param signedPayload
+ * @return
+ * @throws SLCommandoBuildException
+ */
+ public static JsonObject createGenericRequest(String reqId, String transactionId, JsonElement payLoad, String signedPayload) throws SLCommandoBuildException {
+ JsonObject req = new JsonObject();
+ addSingleIntegerElement(req, SL20Constants.SL20_VERSION, SL20Constants.CURRENT_SL20_VERSION, true);
+ addSingleStringElement(req, SL20Constants.SL20_REQID, reqId, true);
+ addSingleStringElement(req, SL20Constants.SL20_TRANSACTIONID, transactionId, false);
+ addOnlyOnceOfTwo(req, SL20Constants.SL20_PAYLOAD, SL20Constants.SL20_SIGNEDPAYLOAD,
+ payLoad, signedPayload);
+ return req;
+
+ }
+
+ /**
+ * Create Generic Response Container
+ *
+ * @param respId
+ * @param inResponseTo
+ * @param transactionId
+ * @param payLoad
+ * @param signedPayload
+ * @return
+ * @throws SLCommandoBuildException
+ */
+ public static final JsonObject createGenericResponse(String respId, String inResponseTo, String transactionId,
+ JsonElement payLoad, String signedPayload) throws SLCommandoBuildException {
+
+ JsonObject req = new JsonObject();
+ addSingleIntegerElement(req, SL20Constants.SL20_VERSION, SL20Constants.CURRENT_SL20_VERSION, true);
+ addSingleStringElement(req, SL20Constants.SL20_RESPID, respId, true);
+ addSingleStringElement(req, SL20Constants.SL20_INRESPTO, inResponseTo, true);
+ addSingleStringElement(req, SL20Constants.SL20_TRANSACTIONID, transactionId, false);
+ addOnlyOnceOfTwo(req, SL20Constants.SL20_PAYLOAD, SL20Constants.SL20_SIGNEDPAYLOAD,
+ payLoad, signedPayload);
+ return req;
+
+ }
+
+ /**
+ * Add one element of two possible elements <br>
+ * This method adds either the first element or the second element to parent JSON, but never both.
+ *
+ * @param parent Parent JSON element
+ * @param firstKeyId first element Id
+ * @param secondKeyId second element Id
+ * @param first first element
+ * @param second second element
+ * @throws SLCommandoBuildException
+ */
+ public static void addOnlyOnceOfTwo(JsonObject parent, String firstKeyId, String secondKeyId, JsonElement first, String second) throws SLCommandoBuildException {
+ if (first == null && (second == null || second.isEmpty())) {
+ log.warn(firstKeyId + " and " + secondKeyId + " is NULL");
+ throw new SLCommandoBuildException();
+
+ } else if (first != null && second != null) {
+ log.warn(firstKeyId + " and " + secondKeyId + " can not SET TWICE");
+ throw new SLCommandoBuildException();
+
+ } else if (first != null)
+ parent.add(firstKeyId, first);
+
+ else if (second != null && !second.isEmpty())
+ parent.addProperty(secondKeyId, second);
+
+ else {
+ log.warn("Internal build error");
+ throw new SLCommandoBuildException();
+
+ }
+ }
+
+ private static void addArrayOfStrings(JsonObject parent, String keyId, List<String> values) throws SLCommandoBuildException {
+ validateParentAndKey(parent, keyId);
+ if (values != null) {
+ JsonArray callReqParamsArray = new JsonArray();
+ parent.add(keyId, callReqParamsArray );
+ for(String el : values)
+ callReqParamsArray.add(el);
+
+ }
+ }
+
+
+ private static void addArrayOfStringElements(JsonObject parent, String keyId, Map<String, String> keyValuePairs) throws SLCommandoBuildException {
+ validateParentAndKey(parent, keyId);
+ if (keyValuePairs != null) {
+ JsonArray callReqParamsArray = new JsonArray();
+ parent.add(keyId, callReqParamsArray );
+
+ for(Entry<String, String> el : keyValuePairs.entrySet()) {
+ JsonObject callReqParams = new JsonObject();
+ //callReqParams.addProperty(SL20Constants.SL20_COMMAND_PARAM_GENERAL_REQPARAMETER_KEY, el.getKey());
+ //callReqParams.addProperty(SL20Constants.SL20_COMMAND_PARAM_GENERAL_REQPARAMETER_VALUE, el.getValue());
+ callReqParams.addProperty(el.getKey(), el.getValue());
+ callReqParamsArray.add(callReqParams);
+
+ }
+ }
+ }
+
+ private static void addSingleCertificateElement(JsonObject parent, String keyId, X509Certificate cert, boolean isRequired) throws CertificateEncodingException, SLCommandoBuildException {
+ if (cert != null)
+ addSingleByteElement(parent, keyId, cert.getEncoded(), isRequired);
+
+ else if (isRequired) {
+ log.warn(keyId + " is marked as REQUIRED");
+ throw new SLCommandoBuildException();
+
+ }
+
+ }
+
+
+
+ private static void addSingleByteElement(JsonObject parent, String keyId, byte[] value, boolean isRequired) throws SLCommandoBuildException {
+ validateParentAndKey(parent, keyId);
+
+ if (isRequired && value == null) {
+ log.warn(keyId + " has NULL value");
+ throw new SLCommandoBuildException();
+
+ } else if (value != null)
+ parent.addProperty(keyId, org.bouncycastle.util.encoders.Base64.toBase64String(value));
+
+ }
+
+ private static void addSingleBooleanElement(JsonObject parent, String keyId, Boolean value, boolean isRequired) throws SLCommandoBuildException {
+ validateParentAndKey(parent, keyId);
+
+ if (isRequired && value == null) {
+ log.warn(keyId + " has a NULL value");
+ throw new SLCommandoBuildException();
+
+ } else if (value != null)
+ parent.addProperty(keyId, value);
+
+ }
+
+ private static void addSingleNumberElement(JsonObject parent, String keyId, Integer value, boolean isRequired) throws SLCommandoBuildException {
+ validateParentAndKey(parent, keyId);
+
+ if (isRequired && value == null) {
+ log.warn(keyId + " has a NULL value");
+ throw new SLCommandoBuildException();
+
+ } else if (value != null)
+ parent.addProperty(keyId, value);;
+
+ }
+
+ private static void addSingleStringElement(JsonObject parent, String keyId, String value, boolean isRequired) throws SLCommandoBuildException {
+ validateParentAndKey(parent, keyId);
+
+ if (isRequired && (value == null || value.isEmpty())) {
+ log.warn(keyId + " has an empty value");
+ throw new SLCommandoBuildException();
+
+ } else if (value != null && !value.isEmpty())
+ parent.addProperty(keyId, value);
+
+ }
+
+ private static void addSingleIntegerElement(JsonObject parent, String keyId, Integer value, boolean isRequired) throws SLCommandoBuildException {
+ validateParentAndKey(parent, keyId);
+
+ if (isRequired && value == null) {
+ log.warn(keyId + " has an empty value");
+ throw new SLCommandoBuildException();
+
+ } else if (value != null)
+ parent.addProperty(keyId, value);
+
+ }
+
+ private static void addSingleJSONElement(JsonObject parent, String keyId, JsonElement element, boolean isRequired) throws SLCommandoBuildException {
+ validateParentAndKey(parent, keyId);
+
+ if (isRequired && element == null) {
+ log.warn("No commando name included");
+ throw new SLCommandoBuildException();
+
+ } else if (element != null)
+ parent.add(keyId, element);
+
+ }
+
+ private static void addOnlyOnceOfTwo(JsonObject parent, String firstKeyId, String secondKeyId, JsonElement first, JsonElement second) throws SLCommandoBuildException {
+ if (first == null && second == null) {
+ log.warn(firstKeyId + " and " + secondKeyId + " is NULL");
+ throw new SLCommandoBuildException();
+
+ } else if (first != null && second != null) {
+ log.warn(firstKeyId + " and " + secondKeyId + " can not SET TWICE");
+ throw new SLCommandoBuildException();
+
+ } else if (first != null)
+ parent.add(firstKeyId, first);
+
+ else if (second != null)
+ parent.add(secondKeyId, second);
+
+ else {
+ log.warn("Internal build error");
+ throw new SLCommandoBuildException();
+
+ }
+ }
+
+ private static void validateParentAndKey(JsonObject parent, String keyId) throws SLCommandoBuildException {
+ if (parent == null) {
+ log.warn("NO parent JSON element");
+ throw new SLCommandoBuildException();
+
+ }
+ if (keyId == null || keyId.isEmpty()) {
+ log.warn("NO JSON element identifier");
+ throw new SLCommandoBuildException();
+
+ }
+ }
+}
diff --git a/pdf-as-lib/src/main/java/at/gv/egiz/sl20/utils/SL20JSONExtractorUtils.java b/pdf-as-lib/src/main/java/at/gv/egiz/sl20/utils/SL20JSONExtractorUtils.java
new file mode 100644
index 00000000..5a438e16
--- /dev/null
+++ b/pdf-as-lib/src/main/java/at/gv/egiz/sl20/utils/SL20JSONExtractorUtils.java
@@ -0,0 +1,422 @@
+package at.gv.egiz.sl20.utils;
+
+import java.io.InputStreamReader;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.Map.Entry;
+
+import org.apache.http.Header;
+import org.apache.http.HttpEntity;
+import org.apache.http.HttpResponse;
+import org.apache.http.client.utils.URIBuilder;
+import org.jose4j.base64url.Base64Url;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.google.gson.JsonElement;
+import com.google.gson.JsonObject;
+import com.google.gson.JsonParser;
+
+import at.gv.egiz.sl20.data.VerificationResult;
+import at.gv.egiz.sl20.exceptions.SL20Exception;
+import at.gv.egiz.sl20.exceptions.SLCommandoParserException;
+
+public class SL20JSONExtractorUtils {
+ private static final Logger log = LoggerFactory.getLogger(SL20JSONExtractorUtils.class);
+
+ /**
+ * Extract String value from JSON
+ *
+ * @param input
+ * @param keyID
+ * @param isRequired
+ * @return
+ * @throws SLCommandoParserException
+ */
+ public static String getStringValue(JsonObject input, String keyID, boolean isRequired) throws SLCommandoParserException {
+ try {
+ JsonElement internal = getAndCheck(input, keyID, isRequired);
+
+ if (internal != null)
+ return internal.getAsString();
+ else
+ return null;
+
+ } catch (SLCommandoParserException e) {
+ throw e;
+
+ } catch (Exception e) {
+ log.warn("Can not extract String value with keyId: " + keyID);
+ throw new SLCommandoParserException(e);
+
+ }
+ }
+
+ /**
+ * Extract Boolean value from JSON
+ *
+ * @param input
+ * @param keyID
+ * @param isRequired
+ * @return
+ * @throws SLCommandoParserException
+ */
+ public static boolean getBooleanValue(JsonObject input, String keyID, boolean isRequired, boolean defaultValue) throws SLCommandoParserException {
+ try {
+ JsonElement internal = getAndCheck(input, keyID, isRequired);
+
+ if (internal != null)
+ return internal.getAsBoolean();
+ else
+ return defaultValue;
+
+ } catch (SLCommandoParserException e) {
+ throw e;
+
+ } catch (Exception e) {
+ log.warn("Can not extract Boolean value with keyId: " + keyID);
+ throw new SLCommandoParserException(e);
+
+ }
+ }
+
+ /**
+ * Extract JSONObject value from JSON
+ *
+ * @param input
+ * @param keyID
+ * @param isRequired
+ * @return
+ * @throws SLCommandoParserException
+ */
+ public static JsonObject getJSONObjectValue(JsonObject input, String keyID, boolean isRequired) throws SLCommandoParserException {
+ try {
+ JsonElement internal = getAndCheck(input, keyID, isRequired);
+
+ if (internal != null)
+ return internal.getAsJsonObject();
+ else
+ return null;
+
+ } catch (SLCommandoParserException e) {
+ throw e;
+
+ } catch (Exception e) {
+ log.warn("Can not extract Boolean value with keyId: \" + keyID");
+ throw new SLCommandoParserException(e);
+
+ }
+ }
+
+ /**
+ * Extract Map of Key/Value pairs from a JSON Element
+ *
+ * @param input parent JSON object
+ * @param keyID KeyId of the child that should be parsed
+ * @param isRequired
+ * @return
+ * @throws SLCommandoParserException
+ */
+ public static Map<String, String> getMapOfStringElements(JsonObject input, String keyID, boolean isRequired) throws SLCommandoParserException {
+ JsonElement internal = getAndCheck(input, keyID, isRequired);
+ return getMapOfStringElements(internal);
+
+ }
+
+ /**
+ * Extract a List of String elements from a JSON element
+ *
+ * @param input
+ * @param isRequired
+ * @param keyID
+ * @return
+ * @throws SLCommandoParserException
+ */
+ public static List<String> getListOfStringElements(JsonObject input, String keyID, boolean isRequired) throws SLCommandoParserException {
+ JsonElement internal = getAndCheck(input, keyID, isRequired);
+
+ List<String> result = new ArrayList<String>();
+ if (internal != null) {
+ if (internal.isJsonArray()) {
+ Iterator<JsonElement> arrayIterator = internal.getAsJsonArray().iterator();
+ while(arrayIterator.hasNext()) {
+ JsonElement next = arrayIterator.next();
+ if (next.isJsonPrimitive())
+ result.add(next.getAsString());
+ }
+
+ } else if (internal.isJsonPrimitive()) {
+ result.add(internal.getAsString());
+
+ } else {
+ log.warn("JSON Element IS NOT a JSON array or a JSON Primitive");
+ throw new SLCommandoParserException();
+ }
+ }
+
+ return result;
+ }
+
+
+ /**
+ * Extract Map of Key/Value pairs from a JSON Element
+ *
+ * @param input
+ * @return
+ * @throws SLCommandoParserException
+ */
+ public static Map<String, String> getMapOfStringElements(JsonElement input) throws SLCommandoParserException {
+ Map<String, String> result = new HashMap<String, String>();
+
+ if (input != null) {
+ if (input.isJsonArray()) {
+ Iterator<JsonElement> arrayIterator = input.getAsJsonArray().iterator();
+ while(arrayIterator.hasNext()) {
+ JsonElement next = arrayIterator.next();
+ Iterator<Entry<String, JsonElement>> entry = next.getAsJsonObject().entrySet().iterator();
+ entitySetToMap(result, entry);
+
+ }
+
+ } else if (input.isJsonObject()) {
+ Iterator<Entry<String, JsonElement>> objectKeys = input.getAsJsonObject().entrySet().iterator();
+ entitySetToMap(result, objectKeys);
+
+ } else {
+ log.warn("JSON Element IS NOT a JSON array or a JSON object");
+ throw new SLCommandoParserException();
+ }
+
+ }
+
+ return result;
+ }
+
+ private static void entitySetToMap(Map<String, String> result, Iterator<Entry<String, JsonElement>> entry) {
+ while (entry.hasNext()) {
+ Entry<String, JsonElement> el = entry.next();
+ if (result.containsKey(el.getKey()))
+ log.info("Attr. Map already contains Element with Key: " + el.getKey() + ". Overwrite element ... ");
+
+ result.put(el.getKey(), el.getValue().getAsString());
+
+ }
+
+ }
+
+
+ public static JsonElement extractSL20Result(JsonObject command, IJOSETools decrypter, boolean mustBeEncrypted) throws SL20Exception {
+ JsonElement result = command.get(SL20Constants.SL20_COMMAND_CONTAINER_RESULT);
+ JsonElement encryptedResult = command.get(SL20Constants.SL20_COMMAND_CONTAINER_ENCRYPTEDRESULT);
+
+ if (result == null && encryptedResult == null) {
+ log.warn("NO result OR encryptedResult FOUND.");
+ throw new SLCommandoParserException();
+
+ } else if (encryptedResult == null && mustBeEncrypted) {
+ log.warn("result MUST be signed.");
+ throw new SLCommandoParserException();
+
+ } else if (encryptedResult != null && encryptedResult.isJsonPrimitive()) {
+ try {
+ return decrypter.decryptPayload(encryptedResult.getAsString());
+
+ } catch (Exception e) {
+ log.info("Can NOT decrypt SL20 result. Reason:" + e.getMessage());
+ if (!mustBeEncrypted) {
+ log.warn("Decrypted results are disabled by configuration. Parse result in plain if it is possible");
+
+ //dummy code
+ try {
+ String[] signedPayload = encryptedResult.toString().split("\\.");
+ JsonElement payLoad = new JsonParser().parse(new String(Base64Url.decodeToUtf8String(signedPayload[1])));
+ return payLoad;
+
+ } catch (Exception e1) {
+ log.debug("DummyCode FAILED, Reason: " + e1.getMessage() + " Ignore it ...");
+ throw new SL20Exception(e.getMessage(), e);
+
+ }
+
+ } else
+ throw e;
+
+ }
+
+ } else if (result != null) {
+ return result;
+
+ } else {
+ log.error("Internal build error");
+ throw new SLCommandoParserException();
+
+ }
+
+
+ }
+
+ /**
+ * Extract payLoad from generic transport container
+ *
+ * @param container
+ * @param joseTools
+ * @return
+ * @throws SLCommandoParserException
+ */
+ public static VerificationResult extractSL20PayLoad(JsonObject container, IJOSETools joseTools, boolean mustBeSigned) throws SL20Exception {
+
+ JsonElement sl20Payload = container.get(SL20Constants.SL20_PAYLOAD);
+ JsonElement sl20SignedPayload = container.get(SL20Constants.SL20_SIGNEDPAYLOAD);
+
+ if (mustBeSigned && joseTools == null) {
+ log.warn("'joseTools' MUST be set if 'mustBeSigned' is 'true'");
+ throw new SLCommandoParserException();
+
+ }
+
+ if (sl20Payload == null && sl20SignedPayload == null) {
+ log.warn("NO payLoad OR signedPayload FOUND.");
+ throw new SLCommandoParserException();
+
+ } else if (sl20SignedPayload == null && mustBeSigned) {
+ log.warn("payLoad MUST be signed.");
+ throw new SLCommandoParserException();
+
+ } else if (joseTools != null && sl20SignedPayload != null && sl20SignedPayload.isJsonPrimitive()) {
+ try {
+ return joseTools.validateSignature(sl20SignedPayload.getAsString());
+
+ } catch (SL20Exception e) {
+ if (!mustBeSigned && sl20Payload == null) {
+ log.debug("Signature verification FAILED with reason: " + e.getMessage()
+ + " but response MUST NOT be signed by configuration"
+ + " Starting backup process ... ");
+ String[] split = sl20SignedPayload.getAsString().split("\\.");
+ if (split.length == 3) {
+ JsonElement payLoad = new JsonParser().parse(new String(Base64Url.decodeToUtf8String(split[1])));
+ log.info("Signature verification FAILED with reason: " + e.getMessage() + " Use plain result as it is");
+ return new VerificationResult(payLoad.getAsJsonObject());
+
+ }
+ }
+
+ throw e;
+
+ }
+
+ } else if (sl20Payload != null)
+ return new VerificationResult(sl20Payload.getAsJsonObject());
+
+ else if (joseTools == null && !mustBeSigned && sl20SignedPayload != null && sl20SignedPayload.isJsonPrimitive()) {
+ log.info("Received signed SL20 response, but verification IS NOT required and NOT CONFIGURATED. Skip signature verification ... ");
+ String[] split = sl20SignedPayload.getAsString().split("\\.");
+ if (split.length == 3) {
+ JsonElement payLoad = new JsonParser().parse(new String(Base64Url.decodeToUtf8String(split[1])));
+ return new VerificationResult(payLoad.getAsJsonObject());
+
+ } else {
+ log.warn("Can NOT skip signature verification, because signed result has an unsupported format!");
+ throw new SLCommandoParserException();
+
+ }
+
+ } else {
+ log.warn("Internal build error");
+ throw new SLCommandoParserException();
+
+ }
+
+
+ }
+
+
+ /**
+ * Extract generic transport container from httpResponse
+ *
+ * @param httpResp
+ * @return
+ * @throws SLCommandoParserException
+ */
+ public static JsonObject getSL20ContainerFromResponse(HttpResponse httpResp) throws SLCommandoParserException {
+ try {
+ JsonObject sl20Resp = null;
+ if (httpResp.getStatusLine().getStatusCode() == 307) {
+ Header[] locationHeader = httpResp.getHeaders("Location");
+ if (locationHeader == null) {
+ log.warn("Find Redirect statuscode but not Location header");
+ throw new SLCommandoParserException();
+
+ }
+ String sl20RespString = new URIBuilder(locationHeader[0].getValue()).getQueryParams().get(0).getValue();
+ sl20Resp = new JsonParser().parse(Base64Url.encode((sl20RespString.getBytes()))).getAsJsonObject();
+
+ } else if (httpResp.getStatusLine().getStatusCode() == 200) {
+ if (!httpResp.getEntity().getContentType().getValue().startsWith("application/json")) {
+ log.warn("SL20 response with a wrong ContentType: " + httpResp.getEntity().getContentType().getValue());
+ throw new SLCommandoParserException();
+
+ }
+ sl20Resp = parseSL20ResultFromResponse(httpResp.getEntity());
+
+ } else if ( (httpResp.getStatusLine().getStatusCode() == 500) ||
+ (httpResp.getStatusLine().getStatusCode() == 401) ||
+ (httpResp.getStatusLine().getStatusCode() == 400) ) {
+ log.info("SL20 response with http-code: " + httpResp.getStatusLine().getStatusCode()
+ + ". Search for error message");
+ sl20Resp = parseSL20ResultFromResponse(httpResp.getEntity());
+
+
+ } else {
+ log.warn("SL20 response with http-code: " + httpResp.getStatusLine().getStatusCode());
+ throw new SLCommandoParserException();
+
+ }
+
+ log.info("Find JSON object in http response");
+ return sl20Resp;
+
+ } catch (Exception e) {
+ log.warn("SL20 response parsing FAILED! Reason: " + e.getMessage(), e);
+ throw new SLCommandoParserException(e);
+
+ }
+ }
+
+ private static JsonObject parseSL20ResultFromResponse(HttpEntity resp) throws Exception {
+ if (resp != null && resp.getContent() != null) {
+ JsonElement sl20Resp = new JsonParser().parse(new InputStreamReader(resp.getContent()));
+ if (sl20Resp != null && sl20Resp.isJsonObject()) {
+ return sl20Resp.getAsJsonObject();
+
+ } else {
+ log.warn("SL2.0 can NOT parse to a JSON object");
+ throw new SLCommandoParserException();
+
+ }
+
+
+ } else {
+ log.warn("Can NOT find content in http response");
+ throw new SLCommandoParserException();
+
+ }
+
+ }
+
+
+ private static JsonElement getAndCheck(JsonObject input, String keyID, boolean isRequired) throws SLCommandoParserException {
+ JsonElement internal = input.get(keyID);
+
+ if (internal == null && isRequired) {
+ log.warn("REQUIRED Element with keyId: " + keyID + " does not exist");
+ throw new SLCommandoParserException();
+
+ }
+
+ return internal;
+
+ }
+}