diff --git a/build.xml b/build.xml
index c58311eb7..634b27de3 100644
--- a/build.xml
+++ b/build.xml
@@ -91,7 +91,7 @@
-
+
diff --git a/pom.xml b/pom.xml
index 298d521d5..a1b463032 100644
--- a/pom.xml
+++ b/pom.xml
@@ -35,7 +35,7 @@
net.sourceforge.plantuml
plantuml
- 1.2021.5-SNAPSHOT
+ 1.2021.6-SNAPSHOT
jar
PlantUML
@@ -94,21 +94,6 @@
1.0.7
test
-
- org.eclipse.elk
- org.eclipse.elk.core
- 0.7.1
-
-
- org.eclipse.elk
- org.eclipse.elk.alg.layered
- 0.7.1
-
-
- org.eclipse.elk
- org.eclipse.elk.alg.mrtree
- 0.7.1
-
diff --git a/skin/plantuml.skin b/skin/plantuml.skin
index ae4a21a2b..55b28739f 100644
--- a/skin/plantuml.skin
+++ b/skin/plantuml.skin
@@ -290,6 +290,10 @@ ganttDiagram {
timeline {
BackgroundColor transparent
}
+ closed {
+ BackGroundColor #E0E8E8
+ FontColor #909898
+ }
task {
RoundCorner 0
Margin 2 2 2 2
diff --git a/src/ext/plantuml/com/at/gadermaier/argon2/Argon2.java b/src/ext/plantuml/com/at/gadermaier/argon2/Argon2.java
new file mode 100644
index 000000000..b4110ed28
--- /dev/null
+++ b/src/ext/plantuml/com/at/gadermaier/argon2/Argon2.java
@@ -0,0 +1,271 @@
+/* This file is taken from
+ https://github.com/andreas1327250/argon2-java
+
+ Original Author: Andreas Gadermaier
+ */
+package ext.plantuml.com.at.gadermaier.argon2;
+
+import static ext.plantuml.com.at.gadermaier.argon2.Constants.Defaults.LANES_DEF;
+import static ext.plantuml.com.at.gadermaier.argon2.Constants.Defaults.LOG_M_COST_DEF;
+import static ext.plantuml.com.at.gadermaier.argon2.Constants.Defaults.OUTLEN_DEF;
+import static ext.plantuml.com.at.gadermaier.argon2.Constants.Defaults.TYPE_DEF;
+import static ext.plantuml.com.at.gadermaier.argon2.Constants.Defaults.T_COST_DEF;
+import static ext.plantuml.com.at.gadermaier.argon2.Constants.Defaults.VERSION_DEF;
+
+import java.nio.ByteBuffer;
+import java.nio.CharBuffer;
+import java.nio.charset.Charset;
+import java.util.Arrays;
+
+import ext.plantuml.com.at.gadermaier.argon2.algorithm.FillMemory;
+import ext.plantuml.com.at.gadermaier.argon2.algorithm.Finalize;
+import ext.plantuml.com.at.gadermaier.argon2.algorithm.Initialize;
+import ext.plantuml.com.at.gadermaier.argon2.model.Argon2Type;
+import ext.plantuml.com.at.gadermaier.argon2.model.Instance;
+
+public class Argon2 {
+
+ private byte[] output;
+ private int outputLength; // -l N
+ private double duration;
+
+ private byte[] password;
+ private byte[] salt;
+ private byte[] secret;
+ private byte[] additional;
+
+ private int iterations; // -t N
+ private int memory; // -m N
+ private int lanes; // -p N
+
+ private int version; // -v (10/13)
+ private Argon2Type type;
+
+ private boolean clearMemory = true;
+ private Charset charset = Charset.forName("UTF-8");
+
+ private boolean encodedOnly = false;
+ private boolean rawOnly = false;
+
+ Argon2() {
+ this.lanes = LANES_DEF;
+ this.outputLength = OUTLEN_DEF;
+ this.memory = 1 << LOG_M_COST_DEF;
+ this.iterations = T_COST_DEF;
+ this.version = VERSION_DEF;
+ this.type = TYPE_DEF;
+ }
+
+ private static byte[] toByteArray(char[] chars, Charset charset) {
+ assert chars != null;
+
+ CharBuffer charBuffer = CharBuffer.wrap(chars);
+ ByteBuffer byteBuffer = charset.encode(charBuffer);
+ byte[] bytes = Arrays.copyOfRange(byteBuffer.array(), byteBuffer.position(), byteBuffer.limit());
+ Arrays.fill(byteBuffer.array(), (byte) 0);
+ return bytes;
+ }
+
+ public void hashNow() {
+ try {
+ Validation.validateInput(this);
+
+ long start = System.nanoTime();
+
+ Instance instance = new Instance(this);
+
+ Initialize.initialize(instance, this);
+ FillMemory.fillMemoryBlocks(instance);
+ Finalize.finalize(instance, this);
+
+ duration = (System.nanoTime() - start) / 1000000000.0;
+ } finally {
+ clear();
+ }
+ }
+
+ public void clear() {
+ if (password != null)
+ Arrays.fill(password, 0, password.length - 1, (byte) 0);
+
+ if (salt != null)
+ Arrays.fill(salt, 0, salt.length - 1, (byte) 0);
+
+ if (secret != null)
+ Arrays.fill(secret, 0, secret.length - 1, (byte) 0);
+
+ if (additional != null)
+ Arrays.fill(additional, 0, additional.length - 1, (byte) 0);
+ }
+
+ void printSummary() {
+ if (encodedOnly)
+ System.out.println(getEncoded());
+ else if (rawOnly)
+ System.out.println(getOutputString());
+ else {
+ System.out.println("Type:\t\t" + type);
+ System.out.println("Iterations:\t" + iterations);
+ System.out.println("Memory:\t\t" + memory + " KiB");
+ System.out.println("Parallelism:\t" + lanes);
+ System.out.println("Hash:\t\t" + getOutputString());
+ System.out.println("Encoded:\t " + getEncoded());
+ System.out.println(duration + " seconds");
+ }
+ }
+
+ public Argon2 setMemoryInKiB(int memory) {
+ this.memory = memory;
+ return this;
+ }
+
+ public Argon2 setParallelism(int parallelism) {
+ this.lanes = parallelism;
+ return this;
+ }
+
+ public Argon2 setPassword(char[] password) {
+ return setPassword(toByteArray(password, charset));
+ }
+
+ public Argon2 setSalt(String salt) {
+ return setSalt(salt.getBytes(charset));
+ }
+
+ public byte[] getOutput() {
+ return output;
+ }
+
+ public void setOutput(byte[] finalResult) {
+ this.output = finalResult;
+ }
+
+ public String getOutputString() {
+ return Util.bytesToHexString(output);
+ }
+
+ public int getOutputLength() {
+ return outputLength;
+ }
+
+ public Argon2 setOutputLength(int outputLength) {
+ this.outputLength = outputLength;
+ return this;
+ }
+
+ public byte[] getPassword() {
+ return password;
+ }
+
+ public Argon2 setPassword(byte[] password) {
+ this.password = password;
+ return this;
+ }
+
+ public int getPasswordLength() {
+ return password.length;
+ }
+
+ public byte[] getSalt() {
+ return salt;
+ }
+
+ public Argon2 setSalt(byte[] salt) {
+ this.salt = salt;
+ return this;
+ }
+
+ public int getSaltLength() {
+ return salt.length;
+ }
+
+ public byte[] getSecret() {
+ return secret;
+ }
+
+ public Argon2 setSecret(byte[] secret) {
+ this.secret = secret;
+ return this;
+ }
+
+ public int getSecretLength() {
+ return secret != null ? secret.length : 0;
+ }
+
+ public byte[] getAdditional() {
+ return additional;
+ }
+
+ public Argon2 setAdditional(byte[] additional) {
+ this.additional = additional;
+ return this;
+ }
+
+ public int getAdditionalLength() {
+ return additional != null ? additional.length : 0;
+ }
+
+ public int getIterations() {
+ return iterations;
+ }
+
+ public Argon2 setIterations(int iterations) {
+ this.iterations = iterations;
+ return this;
+ }
+
+ public int getMemory() {
+ return memory;
+ }
+
+ public Argon2 setMemory(int memory) {
+ this.memory = 1 << memory;
+ return this;
+ }
+
+ public int getLanes() {
+ return lanes;
+ }
+
+ public int getVersion() {
+ return version;
+ }
+
+ public Argon2 setVersion(int version) {
+ this.version = version;
+ return this;
+ }
+
+ public Argon2Type getType() {
+ return type;
+ }
+
+ public Argon2 setType(Argon2Type type) {
+ this.type = type;
+ return this;
+ }
+
+ public boolean isClearMemory() {
+ return clearMemory;
+ }
+
+ public void setClearMemory(boolean clearMemory) {
+ this.clearMemory = clearMemory;
+ }
+
+ public Charset getCharset() {
+ return charset;
+ }
+
+ public void setEncodedOnly(boolean encodedOnly) {
+ this.encodedOnly = encodedOnly;
+ }
+
+ public void setRawOnly(boolean rawOnly) {
+ this.rawOnly = rawOnly;
+ }
+
+ public String getEncoded() {
+ return ""; // TODO
+ }
+}
diff --git a/src/ext/plantuml/com/at/gadermaier/argon2/Argon2Factory.java b/src/ext/plantuml/com/at/gadermaier/argon2/Argon2Factory.java
new file mode 100644
index 000000000..35ee5aa84
--- /dev/null
+++ b/src/ext/plantuml/com/at/gadermaier/argon2/Argon2Factory.java
@@ -0,0 +1,12 @@
+/* This file is taken from
+ https://github.com/andreas1327250/argon2-java
+
+ Original Author: Andreas Gadermaier
+ */
+package ext.plantuml.com.at.gadermaier.argon2;
+
+public class Argon2Factory {
+ public static Argon2 create(){
+ return new Argon2();
+ }
+}
diff --git a/src/ext/plantuml/com/at/gadermaier/argon2/Constants.java b/src/ext/plantuml/com/at/gadermaier/argon2/Constants.java
new file mode 100644
index 000000000..55feec121
--- /dev/null
+++ b/src/ext/plantuml/com/at/gadermaier/argon2/Constants.java
@@ -0,0 +1,102 @@
+/* This file is taken from
+ https://github.com/andreas1327250/argon2-java
+
+ Original Author: Andreas Gadermaier
+ */
+package ext.plantuml.com.at.gadermaier.argon2;
+
+import ext.plantuml.com.at.gadermaier.argon2.model.Argon2Type;
+
+public class Constants {
+
+ /* Memory block size in bytes */
+ public static final int ARGON2_BLOCK_SIZE = 1024;
+ public static final int ARGON2_QWORDS_IN_BLOCK = ARGON2_BLOCK_SIZE / 8;
+ /* Number of pseudo-random values generated by one call to Blake in Argon2i
+ to
+ generate reference block positions
+ */
+ public static final int ARGON2_ADDRESSES_IN_BLOCK = 128;
+ /* Pre-hashing digest length and its extension*/
+ public static final int ARGON2_PREHASH_DIGEST_LENGTH = 64;
+ public static final int ARGON2_PREHASH_SEED_LENGTH = 72;
+ /* Number of synchronization points between lanes per pass */
+ public static final int ARGON2_SYNC_POINTS = 4;
+ /* Flags to determine which fields are securely wiped (default = no wipe). */
+ public static final int ARGON2_DEFAULT_FLAGS = 0;
+ public static final int ARGON2_VERSION_10 = 0x10;
+ public static final int ARGON2_VERSION_13 = 0x13;
+
+ public static class Defaults {
+
+ public static final int OUTLEN_DEF = 32;
+ public static final int T_COST_DEF = 3;
+ public static final int LOG_M_COST_DEF = 12;
+ public static final int LANES_DEF = 1;
+ public static final Argon2Type TYPE_DEF = Argon2Type.Argon2i;
+ public static final int VERSION_DEF = ARGON2_VERSION_13;
+ public static final int ARGON2_VERSION_NUMBER = ARGON2_VERSION_13;
+ public static final boolean ENCODED_ONLY = false;
+ public static final boolean RAW_ONLY = false;
+ }
+ //public static int ARGON2_FLAG_CLEAR_PASSWORD (UINT32_C(1) << 0)
+ //public static int ARGON2_FLAG_CLEAR_SECRET (UINT32_C(1) << 1)
+
+ /*
+ * Argon2 input parameter restrictions
+ */
+ public static class Constraints {
+
+ public static final int MAX_PASSWORD_LEN = 128;
+
+ /* Minimum and maximum number of lanes (degree of parallelism) */
+ public static final int MIN_PARALLELISM = 1;
+ public static final int MAX_PARALLELISM = 16777216;
+
+ /* Minimum and maximum digest size in bytes */
+ public static final int MIN_OUTLEN = 4;
+ public static final int MAX_OUTLEN = Integer.MAX_VALUE;
+
+ /* Minimum and maximum number of memory blocks (each of BLOCK_SIZE bytes) */
+ public static final int MIN_MEMORY = (2 * ARGON2_SYNC_POINTS); /* 2 blocks per slice */
+
+ /* Minimum and maximum number of passes */
+ public static final int MIN_ITERATIONS = 1;
+ public static final int MAX_ITERATIONS = Integer.MAX_VALUE;
+
+ /* Minimum and maximum password length in bytes */
+ public static final int MIN_PWD_LENGTH = 0;
+ public static final int MAX_PWD_LENGTH = Integer.MAX_VALUE;
+
+ /* Minimum and maximum salt length in bytes */
+ public static final int MIN_SALT_LENGTH = 0;
+ public static final int MAX_SALT_LENGTH = Integer.MAX_VALUE;
+
+ /* Minimum and maximum key length in bytes */
+ public static final int MAX_SECRET_LENGTH = Integer.MAX_VALUE;
+
+ /* Minimum and maximum associated model length in bytes */
+ public static final int MAX_AD_LENGTH = Integer.MAX_VALUE;
+ }
+
+ public static class Messages {
+ public static final String P_MIN_MSG = "degree of parallelism cannot be smaller than one";
+ public static final String P_MAX_MSG = "parallelism cannot be greater than 16777216";
+
+ public static final String M_MIN_MSG = "memory too small";
+
+ public static final String T_MIN_MSG = "number of iterations cannot be less than one";
+ public static final String T_MAX_MSG = "number of iterations too high";
+
+ public static final String PWD_MIN_MSG = "password too short";
+ public static final String PWD_MAX_MSG = "password too long";
+
+ public static final String SALT_MIN_MSG = "salt too short";
+ public static final String SALT_MAX_MSG = "salt too long";
+
+ public static final String SECRET_MAX_MSG = "secret too long";
+ public static final String ADDITIONAL_MAX_MSG = "additional data too long";
+
+ }
+
+}
diff --git a/src/ext/plantuml/com/at/gadermaier/argon2/Util.java b/src/ext/plantuml/com/at/gadermaier/argon2/Util.java
new file mode 100644
index 000000000..257c0338c
--- /dev/null
+++ b/src/ext/plantuml/com/at/gadermaier/argon2/Util.java
@@ -0,0 +1,67 @@
+/* This file is taken from
+ https://github.com/andreas1327250/argon2-java
+
+ Original Author: Andreas Gadermaier
+ */
+package ext.plantuml.com.at.gadermaier.argon2;
+
+public class Util {
+
+ public static String bytesToHexString(byte[] bytes) {
+ StringBuilder sb = new StringBuilder();
+ for (byte b : bytes) {
+ sb.append(String.format("%02x", b & 0xff));
+ }
+ return sb.toString();
+ }
+
+ public static byte[] hexStringToByteArray(String s) {
+ int len = s.length();
+ byte[] data = new byte[len / 2];
+ for (int i = 0; i < len; i += 2) {
+ data[i / 2] = (byte) ((Character.digit(s.charAt(i), 16) << 4)
+ + Character.digit(s.charAt(i+1), 16));
+ }
+ return data;
+ }
+
+ public static long littleEndianBytesToLong(byte[] b) {
+ long result = 0;
+ for (int i = 7; i >= 0; i--) {
+ result <<= 8;
+ result |= (b[i] & 0xFF);
+ }
+ return result;
+ }
+
+ public static byte[] intToLittleEndianBytes(int a) {
+ byte[] result = new byte[4];
+ result[0] = (byte) (a & 0xFF);
+ result[1] = (byte) ((a >> 8) & 0xFF);
+ result[2] = (byte) ((a >> 16) & 0xFF);
+ result[3] = (byte) ((a >> 24) & 0xFF);
+ return result;
+ }
+
+ public static byte[] longToLittleEndianBytes(long a) {
+ byte[] result = new byte[8];
+ result[0] = (byte) (a & 0xFF);
+ result[1] = (byte) ((a >> 8) & 0xFF);
+ result[2] = (byte) ((a >> 16) & 0xFF);
+ result[3] = (byte) ((a >> 24) & 0xFF);
+ result[4] = (byte) ((a >> 32) & 0xFF);
+ result[5] = (byte) ((a >> 40) & 0xFF);
+ result[6] = (byte) ((a >> 48) & 0xFF);
+ result[7] = (byte) ((a >> 56) & 0xFF);
+ return result;
+ }
+
+ public static long intToLong(int x){
+ byte[] intBytes = intToLittleEndianBytes(x);
+ byte[] bytes = new byte[8];
+ System.arraycopy(intBytes, 0, bytes, 0, 4);
+ return littleEndianBytesToLong(bytes);
+ }
+
+}
+
diff --git a/src/ext/plantuml/com/at/gadermaier/argon2/Validation.java b/src/ext/plantuml/com/at/gadermaier/argon2/Validation.java
new file mode 100644
index 000000000..199bf2415
--- /dev/null
+++ b/src/ext/plantuml/com/at/gadermaier/argon2/Validation.java
@@ -0,0 +1,63 @@
+/* This file is taken from
+ https://github.com/andreas1327250/argon2-java
+
+ Original Author: Andreas Gadermaier
+ */
+package ext.plantuml.com.at.gadermaier.argon2;
+
+import static ext.plantuml.com.at.gadermaier.argon2.Constants.Constraints.MAX_AD_LENGTH;
+import static ext.plantuml.com.at.gadermaier.argon2.Constants.Constraints.MAX_ITERATIONS;
+import static ext.plantuml.com.at.gadermaier.argon2.Constants.Constraints.MAX_PARALLELISM;
+import static ext.plantuml.com.at.gadermaier.argon2.Constants.Constraints.MAX_PWD_LENGTH;
+import static ext.plantuml.com.at.gadermaier.argon2.Constants.Constraints.MAX_SALT_LENGTH;
+import static ext.plantuml.com.at.gadermaier.argon2.Constants.Constraints.MAX_SECRET_LENGTH;
+import static ext.plantuml.com.at.gadermaier.argon2.Constants.Constraints.MIN_ITERATIONS;
+import static ext.plantuml.com.at.gadermaier.argon2.Constants.Constraints.MIN_PARALLELISM;
+import static ext.plantuml.com.at.gadermaier.argon2.Constants.Constraints.MIN_PWD_LENGTH;
+import static ext.plantuml.com.at.gadermaier.argon2.Constants.Constraints.MIN_SALT_LENGTH;
+import static ext.plantuml.com.at.gadermaier.argon2.Constants.Messages.ADDITIONAL_MAX_MSG;
+import static ext.plantuml.com.at.gadermaier.argon2.Constants.Messages.M_MIN_MSG;
+import static ext.plantuml.com.at.gadermaier.argon2.Constants.Messages.PWD_MAX_MSG;
+import static ext.plantuml.com.at.gadermaier.argon2.Constants.Messages.PWD_MIN_MSG;
+import static ext.plantuml.com.at.gadermaier.argon2.Constants.Messages.P_MAX_MSG;
+import static ext.plantuml.com.at.gadermaier.argon2.Constants.Messages.P_MIN_MSG;
+import static ext.plantuml.com.at.gadermaier.argon2.Constants.Messages.SALT_MAX_MSG;
+import static ext.plantuml.com.at.gadermaier.argon2.Constants.Messages.SALT_MIN_MSG;
+import static ext.plantuml.com.at.gadermaier.argon2.Constants.Messages.SECRET_MAX_MSG;
+import static ext.plantuml.com.at.gadermaier.argon2.Constants.Messages.T_MAX_MSG;
+import static ext.plantuml.com.at.gadermaier.argon2.Constants.Messages.T_MIN_MSG;
+
+import ext.plantuml.com.at.gadermaier.argon2.exception.Argon2InvalidParameterException;
+
+class Validation {
+
+ static void validateInput(Argon2 argon2){
+ String message = null;
+
+ if (argon2.getLanes() < MIN_PARALLELISM)
+ message = P_MIN_MSG;
+ else if (argon2.getLanes() > MAX_PARALLELISM)
+ message = P_MAX_MSG;
+ else if(argon2.getMemory() < 2 * argon2.getLanes())
+ message = M_MIN_MSG;
+ else if(argon2.getIterations() < MIN_ITERATIONS)
+ message = T_MIN_MSG;
+ else if(argon2.getIterations() > MAX_ITERATIONS)
+ message = T_MAX_MSG;
+ else if(argon2.getPasswordLength() < MIN_PWD_LENGTH)
+ message = PWD_MIN_MSG;
+ else if(argon2.getPasswordLength() > MAX_PWD_LENGTH)
+ message = PWD_MAX_MSG;
+ else if(argon2.getSaltLength() < MIN_SALT_LENGTH)
+ message = SALT_MIN_MSG;
+ else if(argon2.getSaltLength() > MAX_SALT_LENGTH)
+ message = SALT_MAX_MSG;
+ else if(argon2.getSecretLength() > MAX_SECRET_LENGTH)
+ message = SECRET_MAX_MSG;
+ else if(argon2.getAdditionalLength() > MAX_AD_LENGTH)
+ message = ADDITIONAL_MAX_MSG;
+
+ if(message != null)
+ throw new Argon2InvalidParameterException(message);
+ }
+}
diff --git a/src/ext/plantuml/com/at/gadermaier/argon2/algorithm/FillBlock.java b/src/ext/plantuml/com/at/gadermaier/argon2/algorithm/FillBlock.java
new file mode 100644
index 000000000..a3024a9f0
--- /dev/null
+++ b/src/ext/plantuml/com/at/gadermaier/argon2/algorithm/FillBlock.java
@@ -0,0 +1,55 @@
+/* This file is taken from
+ https://github.com/andreas1327250/argon2-java
+
+ Original Author: Andreas Gadermaier
+ */
+package ext.plantuml.com.at.gadermaier.argon2.algorithm;
+
+import ext.plantuml.com.at.gadermaier.argon2.model.Block;
+
+class FillBlock {
+
+ static void fillBlock(Block X, Block Y, Block currentBlock, boolean withXor) {
+
+ Block R = new Block();
+ Block Z = new Block();
+
+ R.xor(X, Y);
+ Z.copyBlock(R);
+
+ /* Apply Blake2 on columns of 64-bit words: (0,1,...,15) , then
+ (16,17,..31)... finally (112,113,...127) */
+ for (int i = 0; i < 8; i++) {
+
+ Functions.roundFunction(Z,
+ 16 * i, 16 * i + 1, 16 * i + 2,
+ 16 * i + 3, 16 * i + 4, 16 * i + 5,
+ 16 * i + 6, 16 * i + 7, 16 * i + 8,
+ 16 * i + 9, 16 * i + 10, 16 * i + 11,
+ 16 * i + 12, 16 * i + 13, 16 * i + 14,
+ 16 * i + 15
+ );
+ }
+
+ /* Apply Blake2 on rows of 64-bit words: (0,1,16,17,...112,113), then
+ (2,3,18,19,...,114,115).. finally (14,15,30,31,...,126,127) */
+ for (int i = 0; i < 8; i++) {
+
+ Functions.roundFunction(Z,
+ 2 * i, 2 * i + 1, 2 * i + 16,
+ 2 * i + 17, 2 * i + 32, 2 * i + 33,
+ 2 * i + 48, 2 * i + 49, 2 * i + 64,
+ 2 * i + 65, 2 * i + 80, 2 * i + 81,
+ 2 * i + 96, 2 * i + 97, 2 * i + 112,
+ 2 * i + 113
+ );
+
+ }
+
+ if (withXor) {
+ currentBlock.xor(R, Z, currentBlock);
+ } else {
+ currentBlock.xor(R, Z);
+ }
+ }
+}
diff --git a/src/ext/plantuml/com/at/gadermaier/argon2/algorithm/FillMemory.java b/src/ext/plantuml/com/at/gadermaier/argon2/algorithm/FillMemory.java
new file mode 100644
index 000000000..21f92095c
--- /dev/null
+++ b/src/ext/plantuml/com/at/gadermaier/argon2/algorithm/FillMemory.java
@@ -0,0 +1,80 @@
+/* This file is taken from
+ https://github.com/andreas1327250/argon2-java
+
+ Original Author: Andreas Gadermaier
+ */
+package ext.plantuml.com.at.gadermaier.argon2.algorithm;
+
+import static ext.plantuml.com.at.gadermaier.argon2.Constants.ARGON2_SYNC_POINTS;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+import java.util.concurrent.Future;
+
+import ext.plantuml.com.at.gadermaier.argon2.model.Instance;
+import ext.plantuml.com.at.gadermaier.argon2.model.Position;
+
+public class FillMemory {
+
+ public static void fillMemoryBlocks(Instance instance) {
+ if (instance.getLanes() == 1) {
+ fillMemoryBlockSingleThreaded(instance);
+ } else {
+ fillMemoryBlockMultiThreaded(instance);
+ }
+ }
+
+ private static void fillMemoryBlockSingleThreaded(Instance instance) {
+ for (int i = 0; i < instance.getIterations(); i++) {
+ for (int j = 0; j < ARGON2_SYNC_POINTS; j++) {
+ Position position = new Position(i, 0, j, 0);
+ FillSegment.fillSegment(instance, position);
+ }
+ }
+ }
+
+ private static void fillMemoryBlockMultiThreaded(final Instance instance) {
+
+ ExecutorService service = Executors.newFixedThreadPool(instance.getLanes());
+ List> futures = new ArrayList>();
+
+ for (int i = 0; i < instance.getIterations(); i++) {
+ for (int j = 0; j < ARGON2_SYNC_POINTS; j++) {
+ for (int k = 0; k < instance.getLanes(); k++) {
+
+ final Position position = new Position(i, k, j, 0);
+
+ Future future = service.submit(new Runnable() {
+ @Override
+ public void run() {
+ FillSegment.fillSegment(instance, position);
+ }
+ });
+
+ futures.add(future);
+ }
+
+ joinThreads(instance, futures);
+ }
+ }
+
+ service.shutdownNow();
+ }
+
+ private static void joinThreads(Instance instance, List> futures) {
+ try {
+ for (Future> f : futures) {
+ f.get();
+ }
+ } catch (InterruptedException e) {
+ instance.clear();
+ throw new RuntimeException(e);
+ } catch (ExecutionException e) {
+ instance.clear();
+ throw new RuntimeException(e);
+ }
+ }
+}
diff --git a/src/ext/plantuml/com/at/gadermaier/argon2/algorithm/FillSegment.java b/src/ext/plantuml/com/at/gadermaier/argon2/algorithm/FillSegment.java
new file mode 100644
index 000000000..c11485526
--- /dev/null
+++ b/src/ext/plantuml/com/at/gadermaier/argon2/algorithm/FillSegment.java
@@ -0,0 +1,170 @@
+/* This file is taken from
+ https://github.com/andreas1327250/argon2-java
+
+ Original Author: Andreas Gadermaier
+ */
+package ext.plantuml.com.at.gadermaier.argon2.algorithm;
+
+import static ext.plantuml.com.at.gadermaier.argon2.Constants.ARGON2_ADDRESSES_IN_BLOCK;
+import static ext.plantuml.com.at.gadermaier.argon2.Constants.ARGON2_VERSION_10;
+
+import ext.plantuml.com.at.gadermaier.argon2.Constants;
+import ext.plantuml.com.at.gadermaier.argon2.Util;
+import ext.plantuml.com.at.gadermaier.argon2.model.Argon2Type;
+import ext.plantuml.com.at.gadermaier.argon2.model.Block;
+import ext.plantuml.com.at.gadermaier.argon2.model.Instance;
+import ext.plantuml.com.at.gadermaier.argon2.model.Position;
+
+
+class FillSegment {
+
+ static void fillSegment(Instance instance, Position position) {
+
+ Block addressBlock = null, inputBlock = null, zeroBlock = null;
+
+ boolean dataIndependentAddressing = isDataIndependentAddressing(instance, position);
+ int startingIndex = getStartingIndex(position);
+ int currentOffset = position.lane * instance.getLaneLength() + position.slice * instance.getSegmentLength() + startingIndex;
+ int prevOffset = getPrevOffset(instance, currentOffset);
+
+ if (dataIndependentAddressing) {
+ addressBlock = new Block();
+ zeroBlock = new Block();
+ inputBlock = new Block();
+
+ initAddressBlocks(instance, position, zeroBlock, inputBlock, addressBlock);
+ }
+
+ for (position.index = startingIndex; position.index < instance.getSegmentLength(); position.index++, currentOffset++, prevOffset++) {
+ prevOffset = rotatePrevOffset(instance, currentOffset, prevOffset);
+
+ long pseudoRandom = getPseudoRandom(instance, position, addressBlock, inputBlock, zeroBlock, prevOffset, dataIndependentAddressing);
+ int refLane = getRefLane(instance, position, pseudoRandom);
+ int refColumn = getRefColumn(instance, position, pseudoRandom, refLane == position.lane);
+
+ /* 2 Creating a new block */
+ Block prevBlock = instance.memory[prevOffset];
+ Block refBlock = instance.memory[((instance.getLaneLength()) * refLane + refColumn)];
+ Block currentBlock = instance.memory[currentOffset];
+
+ boolean withXor = isWithXor(instance, position);
+ FillBlock.fillBlock(prevBlock, refBlock, currentBlock, withXor);
+ }
+ }
+
+ private static boolean isDataIndependentAddressing(Instance instance, Position position) {
+ return (instance.getType() == Argon2Type.Argon2i) ||
+ (instance.getType() == Argon2Type.Argon2id
+ && (position.pass == 0)
+ && (position.slice < Constants.ARGON2_SYNC_POINTS / 2)
+ );
+ }
+
+ private static void initAddressBlocks(Instance instance, Position position, Block zeroBlock, Block inputBlock, Block addressBlock) {
+ inputBlock.v[0] = Util.intToLong(position.pass);
+ inputBlock.v[1] = Util.intToLong(position.lane);
+ inputBlock.v[2] = Util.intToLong(position.slice);
+ inputBlock.v[3] = Util.intToLong(instance.memory.length);
+ inputBlock.v[4] = Util.intToLong(instance.getIterations());
+ inputBlock.v[5] = Util.intToLong(instance.getType().ordinal());
+
+ if ((position.pass == 0) && (position.slice == 0)) {
+ /* Don't forget to generate the first block of addresses: */
+ nextAddresses(zeroBlock, inputBlock, addressBlock);
+ }
+ }
+
+ private static boolean isWithXor(Instance instance, Position position) {
+ return !(position.pass == 0 || instance.getVersion() == ARGON2_VERSION_10);
+ }
+
+ private static int getPrevOffset(Instance instance, int currentOffset) {
+ if (currentOffset % instance.getLaneLength() == 0) {
+ /* Last block in this lane */
+ return currentOffset + instance.getLaneLength() - 1;
+ } else {
+ /* Previous block */
+ return currentOffset - 1;
+ }
+ }
+
+ private static int rotatePrevOffset(Instance instance, int currentOffset, int prevOffset) {
+ if (currentOffset % instance.getLaneLength() == 1) {
+ prevOffset = currentOffset - 1;
+ }
+ return prevOffset;
+ }
+
+ private static int getStartingIndex(Position position) {
+ if ((position.pass == 0) && (position.slice == 0)) {
+ return 2; /* we have already generated the first two blocks */
+ } else {
+ return 0;
+ }
+ }
+
+ private static void nextAddresses(Block zeroBlock, Block inputBlock, Block addressBlock) {
+ inputBlock.v[6]++;
+ FillBlock.fillBlock(zeroBlock, inputBlock, addressBlock, false);
+ FillBlock.fillBlock(zeroBlock, addressBlock, addressBlock, false);
+ }
+
+ /* 1.2 Computing the index of the reference block */
+ /* 1.2.1 Taking pseudo-random value from the previous block */
+ private static long getPseudoRandom(Instance instance, Position position, Block addressBlock, Block inputBlock, Block zeroBlock, int prevOffset, boolean dataIndependentAddressing) {
+ if (dataIndependentAddressing) {
+ if (position.index % ARGON2_ADDRESSES_IN_BLOCK == 0) {
+ nextAddresses(zeroBlock, inputBlock, addressBlock);
+ }
+ return addressBlock.v[position.index % ARGON2_ADDRESSES_IN_BLOCK];
+ } else {
+ return instance.memory[prevOffset].v[0];
+ }
+ }
+
+ private static int getRefLane(Instance instance, Position position, long pseudoRandom) {
+ int refLane = (int) (((pseudoRandom >>> 32)) % instance.getLanes());
+
+ if ((position.pass == 0) && (position.slice == 0)) {
+ /* Can not reference other lanes yet */
+ refLane = position.lane;
+ }
+ return refLane;
+ }
+
+ private static int getRefColumn(Instance instance, Position position, long pseudoRandom,
+ boolean sameLane) {
+
+ int referenceAreaSize;
+ int startPosition;
+
+ if (position.pass == 0) {
+ startPosition = 0;
+
+ if (sameLane) {
+ /* The same lane => add current segment */
+ referenceAreaSize = position.slice * instance.getSegmentLength() + position.index - 1;
+ } else {
+ /* pass == 0 && !sameLane => position.slice > 0*/
+ referenceAreaSize = position.slice * instance.getSegmentLength() + ((position.index == 0) ? (-1) : 0);
+ }
+
+ } else {
+ startPosition = ((position.slice + 1) * instance.getSegmentLength()) % instance.getLaneLength();
+
+ if (sameLane) {
+ referenceAreaSize = instance.getLaneLength() - instance.getSegmentLength() + position.index - 1;
+ } else {
+ referenceAreaSize = instance.getLaneLength() - instance.getSegmentLength() + ((position.index == 0) ? (-1) : 0);
+ }
+ }
+
+ long relativePosition = pseudoRandom & 0xFFFFFFFFL;
+// long relativePosition = pseudoRandom << 32 >>> 32;
+ relativePosition = (relativePosition * relativePosition) >>> 32;
+ relativePosition = referenceAreaSize - 1 - (referenceAreaSize * relativePosition >>> 32);
+
+ return (int) (startPosition + relativePosition) % instance.getLaneLength();
+ }
+
+}
diff --git a/src/ext/plantuml/com/at/gadermaier/argon2/algorithm/Finalize.java b/src/ext/plantuml/com/at/gadermaier/argon2/algorithm/Finalize.java
new file mode 100644
index 000000000..af8e6b8a7
--- /dev/null
+++ b/src/ext/plantuml/com/at/gadermaier/argon2/algorithm/Finalize.java
@@ -0,0 +1,34 @@
+/* This file is taken from
+ https://github.com/andreas1327250/argon2-java
+
+ Original Author: Andreas Gadermaier
+ */
+package ext.plantuml.com.at.gadermaier.argon2.algorithm;
+
+import ext.plantuml.com.at.gadermaier.argon2.Argon2;
+import ext.plantuml.com.at.gadermaier.argon2.model.Block;
+import ext.plantuml.com.at.gadermaier.argon2.model.Instance;
+
+public class Finalize {
+
+ public static void finalize(Instance instance, Argon2 argon2) {
+
+ Block finalBlock = instance.memory[instance.getLaneLength() - 1];
+
+ /* XOR the last blocks */
+ for (int i = 1; i < instance.getLanes(); i++) {
+ int lastBlockInLane = i * instance.getLaneLength() + (instance.getLaneLength() - 1);
+ finalBlock.xorWith(instance.memory[lastBlockInLane]);
+ }
+
+ byte[] finalBlockBytes = finalBlock.toBytes();
+ byte[] finalResult = Functions.blake2bLong(finalBlockBytes, argon2.getOutputLength());
+
+ argon2.setOutput(finalResult);
+
+ if (argon2.isClearMemory()) {
+ instance.clear();
+ argon2.clear();
+ }
+ }
+}
diff --git a/src/ext/plantuml/com/at/gadermaier/argon2/algorithm/Functions.java b/src/ext/plantuml/com/at/gadermaier/argon2/algorithm/Functions.java
new file mode 100644
index 000000000..5b407982a
--- /dev/null
+++ b/src/ext/plantuml/com/at/gadermaier/argon2/algorithm/Functions.java
@@ -0,0 +1,172 @@
+/* This file is taken from
+ https://github.com/andreas1327250/argon2-java
+
+ Original Author: Andreas Gadermaier
+ */
+package ext.plantuml.com.at.gadermaier.argon2.algorithm;
+
+import static ext.plantuml.com.at.gadermaier.argon2.Constants.ARGON2_BLOCK_SIZE;
+import static ext.plantuml.com.at.gadermaier.argon2.Constants.ARGON2_PREHASH_DIGEST_LENGTH;
+import static ext.plantuml.com.at.gadermaier.argon2.Constants.ARGON2_PREHASH_SEED_LENGTH;
+
+import ext.plantuml.com.at.gadermaier.argon2.Util;
+import ext.plantuml.com.at.gadermaier.argon2.blake2.Blake2b;
+import ext.plantuml.com.at.gadermaier.argon2.model.Block;
+
+class Functions {
+
+
+ /**
+ * H0 = H64(p, τ, m, t, v, y, |P|, P, |S|, S, |L|, K, |X|, X)
+ * -> 64 byte (ARGON2_PREHASH_DIGEST_LENGTH)
+ */
+ static byte[] initialHash(byte[] lanes, byte[] outputLength,
+ byte[] memory, byte[] iterations,
+ byte[] version, byte[] type,
+ byte[] passwordLength, byte[] password,
+ byte[] saltLength, byte[] salt,
+ byte[] secretLength, byte[] secret,
+ byte[] additionalLength, byte[] additional) {
+
+
+ Blake2b.Param params = new Blake2b.Param()
+ .setDigestLength(ARGON2_PREHASH_DIGEST_LENGTH);
+
+ final Blake2b blake2b = Blake2b.Digest.newInstance(params);
+
+ blake2b.update(lanes);
+ blake2b.update(outputLength);
+ blake2b.update(memory);
+ blake2b.update(iterations);
+ blake2b.update(version);
+ blake2b.update(type);
+
+ blake2b.update(passwordLength);
+ if (password != null) {
+ blake2b.update(password);
+ }
+
+ blake2b.update(saltLength);
+ if (salt != null) {
+ blake2b.update(salt);
+ }
+
+ blake2b.update(secretLength);
+ if (secret != null) {
+ blake2b.update(secret);
+ }
+
+ blake2b.update(additionalLength);
+ if (additional != null) {
+ blake2b.update(additional);
+ }
+
+ byte[] blake2hash = blake2b.digest();
+ assert (blake2hash.length == 64);
+
+ return blake2hash;
+ }
+
+
+ /**
+ * H' - blake2bLong - variable length hash function
+ */
+ static byte[] blake2bLong(byte[] input, int outputLength) {
+
+ assert (input.length == ARGON2_PREHASH_SEED_LENGTH || input.length == ARGON2_BLOCK_SIZE);
+
+ byte[] result = new byte[outputLength];
+ byte[] outlenBytes = Util.intToLittleEndianBytes(outputLength);
+
+ int blake2bLength = 64;
+
+ if (outputLength <= blake2bLength) {
+ result = blake2b(input, outlenBytes, outputLength);
+ } else {
+ byte[] outBuffer;
+
+ /* V1 */
+ outBuffer = blake2b(input, outlenBytes, blake2bLength);
+ System.arraycopy(outBuffer, 0, result, 0, blake2bLength / 2);
+
+ int r = (outputLength / 32) + (outputLength % 32 == 0 ? 0 : 1) - 2;
+
+ int position = blake2bLength / 2;
+ for (int i = 2; i <= r; i++, position += blake2bLength / 2) {
+ /* V2 to Vr */
+ outBuffer = blake2b(outBuffer, null, blake2bLength);
+ System.arraycopy(outBuffer, 0, result, position, blake2bLength / 2);
+ }
+
+ int lastLength = outputLength - 32 * r;
+
+ /* Vr+1 */
+ outBuffer = blake2b(outBuffer, null, lastLength);
+ System.arraycopy(outBuffer, 0, result, position, lastLength);
+ }
+
+ assert (result.length == outputLength);
+ return result;
+ }
+
+ private static byte[] blake2b(byte[] input, byte[] outlenBytes, int outputLength) {
+ Blake2b.Param params = new Blake2b.Param()
+ .setDigestLength(outputLength);
+
+ final Blake2b blake2b = Blake2b.Digest.newInstance(params);
+
+ if (outlenBytes != null)
+ blake2b.update(outlenBytes);
+
+ blake2b.update(input);
+
+ return blake2b.digest();
+ }
+
+ static void roundFunction(Block block,
+ int v0, int v1, int v2, int v3,
+ int v4, int v5, int v6, int v7,
+ int v8, int v9, int v10, int v11,
+ int v12, int v13, int v14, int v15) {
+
+ F(block, v0, v4, v8, v12);
+ F(block, v1, v5, v9, v13);
+ F(block, v2, v6, v10, v14);
+ F(block, v3, v7, v11, v15);
+
+ F(block, v0, v5, v10, v15);
+ F(block, v1, v6, v11, v12);
+ F(block, v2, v7, v8, v13);
+ F(block, v3, v4, v9, v14);
+ }
+
+ private static void F(Block block, int a, int b, int c, int d) {
+ fBlaMka(block, a, b);
+ rotr64(block, d, a, 32);
+
+ fBlaMka(block, c, d);
+ rotr64(block, b, c, 24);
+
+ fBlaMka(block, a, b);
+ rotr64(block, d, a, 16);
+
+ fBlaMka(block, c, d);
+ rotr64(block, b, c, 63);
+ }
+
+ /*designed by the Lyra PHC team */
+ /* a <- a + b + 2*aL*bL
+ * + == addition modulo 2^64
+ * aL = least 32 bit */
+ private static void fBlaMka(Block block, int x, int y) {
+ final long m = 0xFFFFFFFFL;
+ final long xy = (block.v[x] & m) * (block.v[y] & m);
+
+ block.v[x] = block.v[x] + block.v[y] + 2 * xy;
+ }
+
+ private static void rotr64(Block block, int v, int w, long c) {
+ final long temp = block.v[v] ^ block.v[w];
+ block.v[v] = (temp >>> c) | (temp << (64 - c));
+ }
+}
diff --git a/src/ext/plantuml/com/at/gadermaier/argon2/algorithm/Initialize.java b/src/ext/plantuml/com/at/gadermaier/argon2/algorithm/Initialize.java
new file mode 100644
index 000000000..e7940ccce
--- /dev/null
+++ b/src/ext/plantuml/com/at/gadermaier/argon2/algorithm/Initialize.java
@@ -0,0 +1,75 @@
+/* This file is taken from
+ https://github.com/andreas1327250/argon2-java
+
+ Original Author: Andreas Gadermaier
+ */
+package ext.plantuml.com.at.gadermaier.argon2.algorithm;
+
+import static ext.plantuml.com.at.gadermaier.argon2.Constants.ARGON2_BLOCK_SIZE;
+import static ext.plantuml.com.at.gadermaier.argon2.Constants.ARGON2_PREHASH_DIGEST_LENGTH;
+import static ext.plantuml.com.at.gadermaier.argon2.Constants.ARGON2_PREHASH_SEED_LENGTH;
+
+import ext.plantuml.com.at.gadermaier.argon2.Argon2;
+import ext.plantuml.com.at.gadermaier.argon2.Util;
+import ext.plantuml.com.at.gadermaier.argon2.model.Instance;
+
+public class Initialize {
+
+
+ public static void initialize(Instance instance, Argon2 argon2) {
+ byte[] initialHash = Functions.initialHash(
+ Util.intToLittleEndianBytes(argon2.getLanes()),
+ Util.intToLittleEndianBytes(argon2.getOutputLength()),
+ Util.intToLittleEndianBytes(argon2.getMemory()),
+ Util.intToLittleEndianBytes(argon2.getIterations()),
+ Util.intToLittleEndianBytes(argon2.getVersion()),
+ Util.intToLittleEndianBytes(argon2.getType().ordinal()),
+ Util.intToLittleEndianBytes(argon2.getPasswordLength()),
+ argon2.getPassword(),
+ Util.intToLittleEndianBytes(argon2.getSaltLength()),
+ argon2.getSalt(),
+ Util.intToLittleEndianBytes(argon2.getSecretLength()),
+ argon2.getSecret(),
+ Util.intToLittleEndianBytes(argon2.getAdditionalLength()),
+ argon2.getAdditional()
+ );
+ fillFirstBlocks(instance, initialHash);
+ }
+
+ /**
+ * (H0 || 0 || i) 72 byte -> 1024 byte
+ * (H0 || 1 || i) 72 byte -> 1024 byte
+ */
+ private static void fillFirstBlocks(Instance instance, byte[] initialHash) {
+
+ final byte[] zeroBytes = {0, 0, 0, 0};
+ final byte[] oneBytes = {1, 0, 0, 0};
+
+ byte[] initialHashWithZeros = getInitialHashLong(initialHash, zeroBytes);
+ byte[] initialHashWithOnes = getInitialHashLong(initialHash, oneBytes);
+
+ for (int i = 0; i < instance.getLanes(); i++) {
+
+ byte[] iBytes = Util.intToLittleEndianBytes(i);
+
+ System.arraycopy(iBytes, 0, initialHashWithZeros, ARGON2_PREHASH_DIGEST_LENGTH + 4, 4);
+ System.arraycopy(iBytes, 0, initialHashWithOnes, ARGON2_PREHASH_DIGEST_LENGTH + 4, 4);
+
+ byte[] blockhashBytes = Functions.blake2bLong(initialHashWithZeros, ARGON2_BLOCK_SIZE);
+ instance.memory[i * instance.getLaneLength() + 0].fromBytes(blockhashBytes);
+
+ blockhashBytes = Functions.blake2bLong(initialHashWithOnes, ARGON2_BLOCK_SIZE);
+ instance.memory[i * instance.getLaneLength() + 1].fromBytes(blockhashBytes);
+ }
+ }
+
+ private static byte[] getInitialHashLong(byte[] initialHash, byte[] appendix) {
+ byte[] initialHashLong = new byte[ARGON2_PREHASH_SEED_LENGTH];
+
+ System.arraycopy(initialHash, 0, initialHashLong, 0, ARGON2_PREHASH_DIGEST_LENGTH);
+ System.arraycopy(appendix, 0, initialHashLong, ARGON2_PREHASH_DIGEST_LENGTH, 4);
+
+ return initialHashLong;
+ }
+
+}
diff --git a/src/ext/plantuml/com/at/gadermaier/argon2/blake2/Blake2b.java b/src/ext/plantuml/com/at/gadermaier/argon2/blake2/Blake2b.java
new file mode 100644
index 000000000..5a42e8ac8
--- /dev/null
+++ b/src/ext/plantuml/com/at/gadermaier/argon2/blake2/Blake2b.java
@@ -0,0 +1,1288 @@
+
+
+/* This file is taken from
+ https://github.com/alphazero/Blake2b/
+
+ Original Author: Andreas Gadermaier
+ because the repository artifact was not uploaded to maven central repository
+
+ */
+/*
+ A Java implementation of BLAKE2B cryptographic digest algorithm.
+
+ Joubin Mohammad Houshyar
+ bushwick, nyc
+ 02-14-2014
+
+ --
+
+ To the extent possible under law, the author(s) have dedicated all copyright
+ and related and neighboring rights to this software to the public domain
+ worldwide. This software is distributed without any warranty.
+
+ You should have received a copy of the CC0 Public Domain Dedication along with
+ this software. If not, see .
+*/
+
+package ext.plantuml.com.at.gadermaier.argon2.blake2;
+
+
+import static ext.plantuml.com.at.gadermaier.argon2.blake2.Blake2b.Engine.Assert.*;
+import static ext.plantuml.com.at.gadermaier.argon2.blake2.Blake2b.Engine.LittleEndian.*;
+
+import java.io.PrintStream;
+import java.security.Key;
+import java.security.spec.AlgorithmParameterSpec;
+import java.util.Arrays;
+
+
+/** */
+public interface Blake2b {
+ /** */
+ void update(byte[] input);
+
+ // ---------------------------------------------------------------------
+ // API
+ // ---------------------------------------------------------------------
+ // TODO add ByteBuffer variants
+
+ /** */
+ void update(byte input);
+
+ /** */
+ void update(byte[] input, int offset, int len);
+
+ /** */
+ byte[] digest();
+
+ /** */
+ byte[] digest(byte[] input);
+
+ /** */
+ void digest(byte[] output, int offset, int len);
+
+ /** */
+ void reset();
+
+ // ---------------------------------------------------------------------
+ // Specification
+ // ---------------------------------------------------------------------
+ public interface Spec {
+ /** pblock size of blake2b */
+ int param_bytes = 64;
+
+ /** pblock size of blake2b */
+ int block_bytes = 128;
+
+ /** maximum digest size */
+ int max_digest_bytes = 64;
+
+ /** maximum key sie */
+ int max_key_bytes = 64;
+
+ /** maximum salt size */
+ int max_salt_bytes = 16;
+
+ /** maximum personalization string size */
+ int max_personalization_bytes = 16;
+
+ /** length of h space vector array */
+ int state_space_len = 8;
+
+ /** max tree fanout value */
+ int max_tree_fantout = 0xFF;
+
+ /** max tree depth value */
+ int max_tree_depth = 0xFF;
+
+ /** max tree leaf length value.Note that this has uint32 semantics
+ and thus 0xFFFFFFFF is used as max value limit. */
+ int max_tree_leaf_length = 0xFFFFFFFF;
+
+ /** max node offset value. Note that this has uint64 semantics
+ and thus 0xFFFFFFFFFFFFFFFFL is used as max value limit. */
+ long max_node_offset = 0xFFFFFFFFFFFFFFFFL;
+
+ /** max tree inner length value */
+ int max_tree_inner_length = 0xFF;
+
+ /** initialization values map ref-Spec IV[i] -> slice iv[i*8:i*8+7] */
+ long[] IV = {
+ 0x6a09e667f3bcc908L,
+ 0xbb67ae8584caa73bL,
+ 0x3c6ef372fe94f82bL,
+ 0xa54ff53a5f1d36f1L,
+ 0x510e527fade682d1L,
+ 0x9b05688c2b3e6c1fL,
+ 0x1f83d9abfb41bd6bL,
+ 0x5be0cd19137e2179L
+ };
+
+ /** sigma per spec used in compress func generation - for reference only */
+ static byte[][] sigma = {
+ { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 } ,
+ { 14, 10, 4, 8, 9, 15, 13, 6, 1, 12, 0, 2, 11, 7, 5, 3 } ,
+ { 11, 8, 12, 0, 5, 2, 15, 13, 10, 14, 3, 6, 7, 1, 9, 4 } ,
+ { 7, 9, 3, 1, 13, 12, 11, 14, 2, 6, 5, 10, 4, 0, 15, 8 } ,
+ { 9, 0, 5, 7, 2, 4, 10, 15, 14, 1, 11, 12, 6, 8, 3, 13 } ,
+ { 2, 12, 6, 10, 0, 11, 8, 3, 4, 13, 7, 5, 15, 14, 1, 9 } ,
+ { 12, 5, 1, 15, 14, 13, 4, 10, 0, 7, 6, 3, 9, 2, 8, 11 } ,
+ { 13, 11, 7, 14, 12, 1, 3, 9, 5, 0, 15, 4, 8, 6, 2, 10 } ,
+ { 6, 15, 14, 9, 11, 3, 0, 8, 12, 2, 13, 7, 1, 4, 10, 5 } ,
+ { 10, 2, 8, 4, 7, 6, 1, 5, 15, 11, 9, 14, 3, 12, 13 , 0 } ,
+ { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 } ,
+ { 14, 10, 4, 8, 9, 15, 13, 6, 1, 12, 0, 2, 11, 7, 5, 3 }
+ };
+ }
+
+ // ---------------------------------------------------------------------
+ // Blake2b Message Digest
+ // ---------------------------------------------------------------------
+
+ /** Generalized Blake2b digest. */
+ public static class Digest extends Engine implements Blake2b {
+ private Digest (final Param p) { super (p); }
+ private Digest () { super (); }
+
+ public static Digest newInstance () {
+ return new Digest ();
+ }
+ public static Digest newInstance (final int digestLength) {
+ return new Digest (new Param().setDigestLength(digestLength));
+ }
+ public static Digest newInstance (Param p) {
+ return new Digest (p);
+ }
+ }
+
+ // ---------------------------------------------------------------------
+ // Blake2b Message Authentication Code
+ // ---------------------------------------------------------------------
+
+ /** Message Authentication Code (MAC) digest. */
+ public static class Mac extends Engine implements Blake2b {
+ private Mac (final Param p) { super (p); }
+ private Mac () { super (); }
+
+ /** Blake2b.MAC 512 - using default Blake2b.Spec settings with given key */
+ public static Mac newInstance (final byte[] key) {
+ return new Mac (new Param().setKey(key));
+ }
+ /** Blake2b.MAC - using default Blake2b.Spec settings with given key, with given digest length */
+ public static Mac newInstance (final byte[] key, final int digestLength) {
+ return new Mac (new Param().setKey(key).setDigestLength(digestLength));
+ }
+ /** Blake2b.MAC - using default Blake2b.Spec settings with given java.security.Key, with given digest length */
+ public static Mac newInstance (final Key key, final int digestLength) {
+ return new Mac (new Param().setKey(key).setDigestLength(digestLength));
+ }
+ /** Blake2b.MAC - using the specified Parameters.
+ * @param p asserted valid configured Param with key */
+ public static Mac newInstance (Param p) {
+ assert p != null : "Param (p) is null";
+ assert p.hasKey() : "Param (p) not configured with a key";
+ return new Mac (p);
+ }
+ }
+
+ // ---------------------------------------------------------------------
+ // Blake2b Incremental Message Digest (Tree)
+ // ---------------------------------------------------------------------
+
+ /**
+ * Note that Tree is just a convenience class; incremental hash (tree)
+ * can be done directly with the Digest class.
+ *
+ * Further node, that tree does NOT accumulate the leaf hashes --
+ * you need to do that
+ */
+ public static class Tree {
+
+ final int depth;
+ final int fanout;
+ final int leaf_length;
+ final int inner_length;
+ final int digest_length;
+
+ /**
+ *
+ * @param fanout
+ * @param depth
+ * @param leaf_length size of data input for leaf nodes.
+ * @param inner_length note this is used also as digest-length for non-root nodes.
+ * @param digest_length final hash out digest-length for the tree
+ */
+ public Tree (
+ final int depth,
+ final int fanout,
+ final int leaf_length,
+ final int inner_length,
+ final int digest_length
+ ) {
+ this.fanout = fanout;
+ this.depth = depth;
+ this.leaf_length = leaf_length;
+ this.inner_length = inner_length;
+ this.digest_length = digest_length;
+ }
+ private Param treeParam() {
+ return new Param().
+ setDepth(depth).setFanout(fanout).setLeafLength(leaf_length).setInnerLength(inner_length);
+ }
+ /** returns the Digest for tree node @ (depth, offset) */
+ public final Digest getNode (final int depth, final int offset) {
+ final Param nodeParam = treeParam().setNodeDepth(depth).setNodeOffset(offset).setDigestLength(inner_length);
+ return Digest.newInstance(nodeParam);
+ }
+ /** returns the Digest for root node */
+ public final Digest getRoot () {
+ final int depth = this.depth - 1;
+ final Param rootParam = treeParam().setNodeDepth(depth).setNodeOffset(0L).setDigestLength(digest_length);
+ return Digest.newInstance(rootParam);
+ }
+ }
+
+ // ---------------------------------------------------------------------
+ // Engine
+ // ---------------------------------------------------------------------
+ static class Engine implements Blake2b {
+
+ /* G0 sigmas */
+ static final int[] sig_g00 = { 0, 14, 11, 7, 9, 2, 12, 13, 6, 10, 0, 14, };
+ static final int[] sig_g01 = { 1, 10, 8, 9, 0, 12, 5, 11, 15, 2, 1, 10, };
+
+ /* G1 sigmas */
+ static final int[] sig_g10 = { 2, 4, 12, 3, 5, 6, 1, 7, 14, 8, 2, 4, };
+ static final int[] sig_g11 = { 3, 8, 0, 1, 7, 10, 15, 14, 9, 4, 3, 8, };
+
+ /* G2 sigmas */
+ static final int[] sig_g20 = { 4, 9, 5, 13, 2, 0, 14, 12, 11, 7, 4, 9, };
+ static final int[] sig_g21 = { 5, 15, 2, 12, 4, 11, 13, 1, 3, 6, 5, 15, };
+
+ /* G3 sigmas */
+ static final int[] sig_g30 = { 6, 13, 15, 11, 10, 8, 4, 3, 0, 1, 6, 13, };
+ static final int[] sig_g31 = { 7, 6, 13, 14, 15, 3, 10, 9, 8, 5, 7, 6, };
+
+ /* G4 sigmas */
+ static final int[] sig_g40 = { 8, 1, 10, 2, 14, 4, 0, 5, 12, 15, 8, 1, };
+ static final int[] sig_g41 = { 9, 12, 14, 6, 1, 13, 7, 0, 2, 11, 9, 12, };
+
+ /* G5 sigmas */
+ static final int[] sig_g50 = { 10, 0, 3, 5, 11, 7, 6, 15, 13, 9, 10, 0, };
+ static final int[] sig_g51 = { 11, 2, 6, 10, 12, 5, 3, 4, 7, 14, 11, 2, };
+
+ /* G6 sigmas */
+ static final int[] sig_g60 = { 12, 11, 7, 4, 6, 15, 9, 8, 1, 3, 12, 11, };
+ static final int[] sig_g61 = { 13, 7, 1, 0, 8, 14, 2, 6, 4, 12, 13, 7, };
+
+ /* G7 sigmas */
+ static final int[] sig_g70 = { 14, 5, 9, 15, 3, 1, 8, 2, 10, 13, 14, 5, };
+ static final int[] sig_g71 = { 15, 3, 4, 8, 13, 9, 11, 10, 5, 0, 15, 3, };
+
+ // ---------------------------------------------------------------------
+ // Blake2b State(+) per reference implementation
+ // ---------------------------------------------------------------------
+ // REVU: address last_node TODO part of the Tree/incremental
+ /**
+ * read only
+ */
+ private static byte[] zeropad = new byte[Spec.block_bytes];
+ /**
+ * per spec
+ */
+ private final long[] h = new long [ 8 ];
+ /** per spec */
+ private final long[] t = new long [ 2 ];
+ /** per spec */
+ private final long[] f = new long [ 2 ];
+ /** pulled up 2b optimal */
+ private final long[] m = new long [16];
+ /** pulled up 2b optimal */
+ private final long[] v = new long [16];
+
+ /** compressor cache buffer */
+ private final byte[] buffer;
+ /** configuration params */
+ private final Param param;
+ /** digest length from init param - copied here on init */
+ private final int outlen;
+ /**
+ * per spec (tree)
+ */
+ private boolean last_node = false;
+ /**
+ * compressor cache buffer offset/cached data length
+ */
+ private int buflen;
+ /** to support update(byte) */
+ private byte[] oneByte;
+
+ /** Basic use constructor pending (TODO) JCA/JCE compliance */
+ Engine() {
+ this(new Param());
+ }
+
+ // ---------------------------------------------------------------------
+ // Ctor & Initialization
+ // ---------------------------------------------------------------------
+
+ /** User provided Param for custom configurations */
+ Engine(final Param param) {
+ assert param != null : "param is null";
+ this.param = param;
+ this.buffer = new byte[Spec.block_bytes];
+ this.oneByte = new byte[1];
+ this.outlen = param.getDigestLength();
+
+ if (param.getDepth() > Param.Default.depth) {
+ final int ndepth = param.getNodeDepth();
+ final long nxoff = param.getNodeOffset();
+ if (ndepth == param.getDepth() - 1) {
+ last_node = true;
+ assert param.getNodeOffset() == 0 : "root must have offset of zero";
+ } else if (param.getNodeOffset() == param.getFanout() - 1) {
+ this.last_node = true;
+ }
+ }
+
+ initialize();
+
+// Debug.dumpBuffer(System.out, "param bytes at init", param.getBytes());
+
+ }
+
+ public static void main(String... args) {
+ Blake2b mac = Blake2b.Mac.newInstance("LOVE".getBytes());
+ final byte[] hash = mac.digest("Salaam!".getBytes());
+// Debug.dumpBuffer(System.out, "-- mac hash --", hash);
+ }
+
+ private void initialize () {
+ // state vector h - copy values to address reset() requests
+ System.arraycopy( param.initialized_H(), 0, this.h, 0, Spec.state_space_len);
+
+// Debug.dumpArray("init H", this.h);
+ // if we have a key update initial block
+ // Note param has zero padded key_bytes to Spec.max_key_bytes
+ if(param.hasKey){
+ this.update (param.key_bytes, 0, Spec.block_bytes);
+ }
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ final public void reset() {
+ // reset cache
+ this.buflen = 0;
+ for (int i = 0; i < buffer.length; i++) {
+ buffer[i] = (byte) 0;
+ }
+
+ // reset flags
+ this.f[0] = 0L;
+ this.f[1] = 0L;
+
+ // reset counters
+ this.t[0] = 0L;
+ this.t[1] = 0L;
+
+ // reset state vector
+ // NOTE: keep as last stmt as init calls update0 for MACs.
+ initialize();
+ }
+
+ // ---------------------------------------------------------------------
+ // interface: Blake2b API
+ // ---------------------------------------------------------------------
+
+ /** {@inheritDoc} */
+ @Override final public void update (final byte[] b, int off, int len) {
+ if (b == null) {
+ throw new IllegalArgumentException("input buffer (b) is null");
+ }
+ /* zero or more calls to compress */
+ // REVU: possibly the double buffering of c-ref is more sensible ..
+ // regardless, the hotspot is in the compress, as expected.
+ while (len > 0) {
+ if ( buflen == 0) {
+ /* try compressing direct from input ? */
+ while ( len > Spec.block_bytes ) {
+ this.t[0] += Spec.block_bytes;
+ this.t[1] += this.t[0] == 0 ? 1 : 0;
+ compress( b, off);
+ len -= Spec.block_bytes;
+ off += Spec.block_bytes;
+ }
+ } else if ( buflen == Spec.block_bytes ) {
+ /* flush */
+ this.t[0] += Spec.block_bytes;
+ this.t[1] += this.t[0] == 0 ? 1 : 0;
+ compress( buffer, 0 );
+ buflen = 0;
+ continue;
+ }
+
+ // "are we there yet?"
+ if( len == 0 ) return;
+
+ final int cap = Spec.block_bytes - buflen;
+ final int fill = len > cap ? cap : len;
+ System.arraycopy( b, off, buffer, buflen, fill );
+ buflen += fill;
+ len -= fill;
+ off += fill;
+ }
+ }
+
+ /** {@inheritDoc} */
+ @Override final public void update (byte b) {
+ oneByte[0] = b;
+ update (oneByte, 0, 1);
+ }
+
+ /** {@inheritDoc} */
+ @Override final public void update(byte[] input) {
+ update (input, 0, input.length);
+ }
+
+ /** {@inheritDoc} */
+ @Override final public void digest(byte[] output, int off, int len) {
+ // zero pad last block; set last block flags; and compress
+ System.arraycopy( zeropad, 0, buffer, buflen, Spec.block_bytes - buflen);
+ if(buflen > 0) {
+ this.t[0] += buflen;
+ this.t[1] += this.t[0] == 0 ? 1 : 0;
+ }
+
+ this.f[ flag.last_block ] = 0xFFFFFFFFFFFFFFFFL;
+ this.f[ flag.last_node ] = this.last_node ? 0xFFFFFFFFFFFFFFFFL : 0x0L;
+
+ // compres and write final out (truncated to len) to output
+ compress( buffer, 0 );
+ hashout( output, off, len );
+
+ reset();
+ }
+
+ /** {@inheritDoc} */
+ @Override final public byte[] digest () throws IllegalArgumentException {
+ final byte[] out = new byte [outlen];
+ digest ( out, 0, outlen );
+ return out;
+ }
+
+ /** {@inheritDoc} */
+ @Override final public byte[] digest (byte[] input) {
+ update(input, 0, input.length);
+ return digest();
+ }
+
+ /**
+ * write out the digest output from the 'h' registers.
+ * truncate full output if necessary.
+ */
+ private void hashout (final byte[] out, final int offset, final int hashlen) {
+ // write max number of whole longs
+ final int lcnt = hashlen >>> 3;
+ long v = 0;
+ int i = offset;
+ for (int w = 0; w < lcnt; w++) {
+ v = h [ w ];
+ out [ i++ ] = (byte) v; v >>>= 8;
+ out [ i++ ] = (byte) v; v >>>= 8;
+ out [ i++ ] = (byte) v; v >>>= 8;
+ out [ i++ ] = (byte) v; v >>>= 8;
+ out [ i++ ] = (byte) v; v >>>= 8;
+ out [ i++ ] = (byte) v; v >>>= 8;
+ out [ i++ ] = (byte) v; v >>>= 8;
+ out [ i++ ] = (byte) v;
+ }
+
+ // basta?
+ if( hashlen == Spec.max_digest_bytes) return;
+
+ // write the remaining bytes of a partial long value
+ v = h[lcnt];
+ i = lcnt << 3;
+ while (i < hashlen) {
+ out[offset + i] = (byte) v;
+ v >>>= 8;
+ ++i;
+ }
+ }
+
+ // ---------------------------------------------------------------------
+ // Internal Ops
+ // ---------------------------------------------------------------------
+
+ /** compress Spec.block_bytes data from b, from offset */
+ private void compress(final byte[] b, final int offset) {
+
+ // set m registers
+ // REVU: some small gains still possible here.
+ m[0] = ((long) b[offset] & 0xFF);
+ m[0] |= ((long) b[offset + 1] & 0xFF) << 8;
+ m[0] |= ((long) b[offset + 2] & 0xFF) << 16;
+ m[0] |= ((long) b[offset + 3] & 0xFF) << 24;
+ m[0] |= ((long) b[offset + 4] & 0xFF) << 32;
+ m[0] |= ((long) b[offset + 5] & 0xFF) << 40;
+ m[0] |= ((long) b[offset + 6] & 0xFF) << 48;
+ m[0] |= ((long) b[offset + 7]) << 56;
+
+ m[1] = ((long) b[offset + 8] & 0xFF);
+ m[1] |= ((long) b[offset + 9] & 0xFF) << 8;
+ m[1] |= ((long) b[offset + 10] & 0xFF) << 16;
+ m[1] |= ((long) b[offset + 11] & 0xFF) << 24;
+ m[1] |= ((long) b[offset + 12] & 0xFF) << 32;
+ m[1] |= ((long) b[offset + 13] & 0xFF) << 40;
+ m[1] |= ((long) b[offset + 14] & 0xFF) << 48;
+ m[1] |= ((long) b[offset + 15]) << 56;
+
+ m[2] = ((long) b[offset + 16] & 0xFF);
+ m[2] |= ((long) b[offset + 17] & 0xFF) << 8;
+ m[2] |= ((long) b[offset + 18] & 0xFF) << 16;
+ m[2] |= ((long) b[offset + 19] & 0xFF) << 24;
+ m[2] |= ((long) b[offset + 20] & 0xFF) << 32;
+ m[2] |= ((long) b[offset + 21] & 0xFF) << 40;
+ m[2] |= ((long) b[offset + 22] & 0xFF) << 48;
+ m[2] |= ((long) b[offset + 23]) << 56;
+
+ m[3] = ((long) b[offset + 24] & 0xFF);
+ m[3] |= ((long) b[offset + 25] & 0xFF) << 8;
+ m[3] |= ((long) b[offset + 26] & 0xFF) << 16;
+ m[3] |= ((long) b[offset + 27] & 0xFF) << 24;
+ m[3] |= ((long) b[offset + 28] & 0xFF) << 32;
+ m[3] |= ((long) b[offset + 29] & 0xFF) << 40;
+ m[3] |= ((long) b[offset + 30] & 0xFF) << 48;
+ m[3] |= ((long) b[offset + 31]) << 56;
+
+ m[4] = ((long) b[offset + 32] & 0xFF);
+ m[4] |= ((long) b[offset + 33] & 0xFF) << 8;
+ m[4] |= ((long) b[offset + 34] & 0xFF) << 16;
+ m[4] |= ((long) b[offset + 35] & 0xFF) << 24;
+ m[4] |= ((long) b[offset + 36] & 0xFF) << 32;
+ m[4] |= ((long) b[offset + 37] & 0xFF) << 40;
+ m[4] |= ((long) b[offset + 38] & 0xFF) << 48;
+ m[4] |= ((long) b[offset + 39]) << 56;
+
+ m[5] = ((long) b[offset + 40] & 0xFF);
+ m[5] |= ((long) b[offset + 41] & 0xFF) << 8;
+ m[5] |= ((long) b[offset + 42] & 0xFF) << 16;
+ m[5] |= ((long) b[offset + 43] & 0xFF) << 24;
+ m[5] |= ((long) b[offset + 44] & 0xFF) << 32;
+ m[5] |= ((long) b[offset + 45] & 0xFF) << 40;
+ m[5] |= ((long) b[offset + 46] & 0xFF) << 48;
+ m[5] |= ((long) b[offset + 47]) << 56;
+
+ m[6] = ((long) b[offset + 48] & 0xFF);
+ m[6] |= ((long) b[offset + 49] & 0xFF) << 8;
+ m[6] |= ((long) b[offset + 50] & 0xFF) << 16;
+ m[6] |= ((long) b[offset + 51] & 0xFF) << 24;
+ m[6] |= ((long) b[offset + 52] & 0xFF) << 32;
+ m[6] |= ((long) b[offset + 53] & 0xFF) << 40;
+ m[6] |= ((long) b[offset + 54] & 0xFF) << 48;
+ m[6] |= ((long) b[offset + 55]) << 56;
+
+ m[7] = ((long) b[offset + 56] & 0xFF);
+ m[7] |= ((long) b[offset + 57] & 0xFF) << 8;
+ m[7] |= ((long) b[offset + 58] & 0xFF) << 16;
+ m[7] |= ((long) b[offset + 59] & 0xFF) << 24;
+ m[7] |= ((long) b[offset + 60] & 0xFF) << 32;
+ m[7] |= ((long) b[offset + 61] & 0xFF) << 40;
+ m[7] |= ((long) b[offset + 62] & 0xFF) << 48;
+ m[7] |= ((long) b[offset + 63]) << 56;
+
+ m[8] = ((long) b[offset + 64] & 0xFF);
+ m[8] |= ((long) b[offset + 65] & 0xFF) << 8;
+ m[8] |= ((long) b[offset + 66] & 0xFF) << 16;
+ m[8] |= ((long) b[offset + 67] & 0xFF) << 24;
+ m[8] |= ((long) b[offset + 68] & 0xFF) << 32;
+ m[8] |= ((long) b[offset + 69] & 0xFF) << 40;
+ m[8] |= ((long) b[offset + 70] & 0xFF) << 48;
+ m[8] |= ((long) b[offset + 71]) << 56;
+
+ m[9] = ((long) b[offset + 72] & 0xFF);
+ m[9] |= ((long) b[offset + 73] & 0xFF) << 8;
+ m[9] |= ((long) b[offset + 74] & 0xFF) << 16;
+ m[9] |= ((long) b[offset + 75] & 0xFF) << 24;
+ m[9] |= ((long) b[offset + 76] & 0xFF) << 32;
+ m[9] |= ((long) b[offset + 77] & 0xFF) << 40;
+ m[9] |= ((long) b[offset + 78] & 0xFF) << 48;
+ m[9] |= ((long) b[offset + 79]) << 56;
+
+ m[10] = ((long) b[offset + 80] & 0xFF);
+ m[10] |= ((long) b[offset + 81] & 0xFF) << 8;
+ m[10] |= ((long) b[offset + 82] & 0xFF) << 16;
+ m[10] |= ((long) b[offset + 83] & 0xFF) << 24;
+ m[10] |= ((long) b[offset + 84] & 0xFF) << 32;
+ m[10] |= ((long) b[offset + 85] & 0xFF) << 40;
+ m[10] |= ((long) b[offset + 86] & 0xFF) << 48;
+ m[10] |= ((long) b[offset + 87]) << 56;
+
+ m[11] = ((long) b[offset + 88] & 0xFF);
+ m[11] |= ((long) b[offset + 89] & 0xFF) << 8;
+ m[11] |= ((long) b[offset + 90] & 0xFF) << 16;
+ m[11] |= ((long) b[offset + 91] & 0xFF) << 24;
+ m[11] |= ((long) b[offset + 92] & 0xFF) << 32;
+ m[11] |= ((long) b[offset + 93] & 0xFF) << 40;
+ m[11] |= ((long) b[offset + 94] & 0xFF) << 48;
+ m[11] |= ((long) b[offset + 95]) << 56;
+
+ m[12] = ((long) b[offset + 96] & 0xFF);
+ m[12] |= ((long) b[offset + 97] & 0xFF) << 8;
+ m[12] |= ((long) b[offset + 98] & 0xFF) << 16;
+ m[12] |= ((long) b[offset + 99] & 0xFF) << 24;
+ m[12] |= ((long) b[offset + 100] & 0xFF) << 32;
+ m[12] |= ((long) b[offset + 101] & 0xFF) << 40;
+ m[12] |= ((long) b[offset + 102] & 0xFF) << 48;
+ m[12] |= ((long) b[offset + 103]) << 56;
+
+ m[13] = ((long) b[offset + 104] & 0xFF);
+ m[13] |= ((long) b[offset + 105] & 0xFF) << 8;
+ m[13] |= ((long) b[offset + 106] & 0xFF) << 16;
+ m[13] |= ((long) b[offset + 107] & 0xFF) << 24;
+ m[13] |= ((long) b[offset + 108] & 0xFF) << 32;
+ m[13] |= ((long) b[offset + 109] & 0xFF) << 40;
+ m[13] |= ((long) b[offset + 110] & 0xFF) << 48;
+ m[13] |= ((long) b[offset + 111]) << 56;
+
+ m[14] = ((long) b[offset + 112] & 0xFF);
+ m[14] |= ((long) b[offset + 113] & 0xFF) << 8;
+ m[14] |= ((long) b[offset + 114] & 0xFF) << 16;
+ m[14] |= ((long) b[offset + 115] & 0xFF) << 24;
+ m[14] |= ((long) b[offset + 116] & 0xFF) << 32;
+ m[14] |= ((long) b[offset + 117] & 0xFF) << 40;
+ m[14] |= ((long) b[offset + 118] & 0xFF) << 48;
+ m[14] |= ((long) b[offset + 119]) << 56;
+
+ m[15] = ((long) b[offset + 120] & 0xFF);
+ m[15] |= ((long) b[offset + 121] & 0xFF) << 8;
+ m[15] |= ((long) b[offset + 122] & 0xFF) << 16;
+ m[15] |= ((long) b[offset + 123] & 0xFF) << 24;
+ m[15] |= ((long) b[offset + 124] & 0xFF) << 32;
+ m[15] |= ((long) b[offset + 125] & 0xFF) << 40;
+ m[15] |= ((long) b[offset + 126] & 0xFF) << 48;
+ m[15] |= ((long) b[offset + 127 ] ) << 56;
+// Debug.dumpArray("m @ compress", m);
+//
+// Debug.dumpArray("h @ compress", h);
+// Debug.dumpArray("t @ compress", t);
+// Debug.dumpArray("f @ compress", f);
+
+ // set v registers
+ v[0] = h[0];
+ v[1] = h[1];
+ v[2] = h[2];
+ v[3] = h[3];
+ v[4] = h[4];
+ v[5] = h[5];
+ v[6] = h[6];
+ v[7] = h[7];
+ v[8] = 0x6a09e667f3bcc908L;
+ v[9] = 0xbb67ae8584caa73bL;
+ v[10] = 0x3c6ef372fe94f82bL;
+ v[11] = 0xa54ff53a5f1d36f1L;
+ v[12] = t[0] ^ 0x510e527fade682d1L;
+ v[13] = t[1] ^ 0x9b05688c2b3e6c1fL;
+ v[14] = f[0] ^ 0x1f83d9abfb41bd6bL;
+ v[15] = f[1] ^ 0x5be0cd19137e2179L;
+
+// Debug.dumpArray("v @ compress", v);
+ // the rounds
+ // REVU: let's try unrolling this again TODO do & bench
+ for (int r = 0; r < 12; r++) {
+
+ /** G (r, 0, 0, 4, 8, 12); */
+
+ v[0] = v[0] + v[4] + m[sig_g00[r]];
+ v[12] ^= v[0];
+ v[12] = (v[12] << 32) | (v[12] >>> 32);
+ v[8] = v[8] + v[12];
+ v[4] ^= v[8];
+ v[4] = (v[4] >>> 24) | (v[4] << 40);
+ v[0] = v[0] + v[4] + m[sig_g01[r]];
+ v[12] ^= v[0];
+ v[12] = (v[12] >>> 16) | (v[12] << 48);
+ v[8] = v[8] + v[12];
+ v[4] ^= v[8];
+ v[4] = (v[4] << 1) | (v[4] >>> 63);
+
+ /** G (r, 1, 1, 5, 9, 13); */
+
+ v[1] = v[1] + v[5] + m[sig_g10[r]];
+ v[13] ^= v[1];
+ v[13] = (v[13] << 32) | (v[13] >>> 32);
+ v[9] = v[9] + v[13];
+ v[5] ^= v[9];
+ v[5] = (v[5] >>> 24) | (v[5] << 40);
+ v[1] = v[1] + v[5] + m[sig_g11[r]];
+ v[13] ^= v[1];
+ v[13] = (v[13] >>> 16) | (v[13] << 48);
+ v[9] = v[9] + v[13];
+ v[5] ^= v[9];
+ v[5] = (v[5] << 1) | (v[5] >>> 63);
+
+ /** G (r, 2, 2, 6, 10, 14); */
+
+ v[2] = v[2] + v[6] + m[sig_g20[r]];
+ v[14] ^= v[2];
+ v[14] = (v[14] << 32) | (v[14] >>> 32);
+ v[10] = v[10] + v[14];
+ v[6] ^= v[10];
+ v[6] = (v[6] >>> 24) | (v[6] << 40);
+ v[2] = v[2] + v[6] + m[sig_g21[r]];
+ v[14] ^= v[2];
+ v[14] = (v[14] >>> 16) | (v[14] << 48);
+ v[10] = v[10] + v[14];
+ v[6] ^= v[10];
+ v[6] = (v[6] << 1) | (v[6] >>> 63);
+
+ /** G (r, 3, 3, 7, 11, 15); */
+
+ v[3] = v[3] + v[7] + m[sig_g30[r]];
+ v[15] ^= v[3];
+ v[15] = (v[15] << 32) | (v[15] >>> 32);
+ v[11] = v[11] + v[15];
+ v[7] ^= v[11];
+ v[7] = (v[7] >>> 24) | (v[7] << 40);
+ v[3] = v[3] + v[7] + m[sig_g31[r]];
+ v[15] ^= v[3];
+ v[15] = (v[15] >>> 16) | (v[15] << 48);
+ v[11] = v[11] + v[15];
+ v[7] ^= v[11];
+ v[7] = (v[7] << 1) | (v[7] >>> 63);
+
+ /** G (r, 4, 0, 5, 10, 15); */
+
+ v[0] = v[0] + v[5] + m[sig_g40[r]];
+ v[15] ^= v[0];
+ v[15] = (v[15] << 32) | (v[15] >>> 32);
+ v[10] = v[10] + v[15];
+ v[5] ^= v[10];
+ v[5] = (v[5] >>> 24) | (v[5] << 40);
+ v[0] = v[0] + v[5] + m[sig_g41[r]];
+ v[15] ^= v[0];
+ v[15] = (v[15] >>> 16) | (v[15] << 48);
+ v[10] = v[10] + v[15];
+ v[5] ^= v[10];
+ v[5] = (v[5] << 1) | (v[5] >>> 63);
+
+ /** G (r, 5, 1, 6, 11, 12); */
+
+ v[1] = v[1] + v[6] + m[sig_g50[r]];
+ v[12] ^= v[1];
+ v[12] = (v[12] << 32) | (v[12] >>> 32);
+ v[11] = v[11] + v[12];
+ v[6] ^= v[11];
+ v[6] = (v[6] >>> 24) | (v[6] << 40);
+ v[1] = v[1] + v[6] + +m[sig_g51[r]];
+ v[12] ^= v[1];
+ v[12] = (v[12] >>> 16) | (v[12] << 48);
+ v[11] = v[11] + v[12];
+ v[6] ^= v[11];
+ v[6] = (v[6] << 1) | (v[6] >>> 63);
+
+ /** G (r, 6, 2, 7, 8, 13); */
+
+ v[2] = v[2] + v[7] + m[sig_g60[r]];
+ v[13] ^= v[2];
+ v[13] = (v[13] << 32) | (v[13] >>> 32);
+ v[8] = v[8] + v[13];
+ v[7] ^= v[8];
+ v[7] = (v[7] >>> 24) | (v[7] << 40);
+ v[2] = v[2] + v[7] + m[sig_g61[r]];
+ v[13] ^= v[2];
+ v[13] = (v[13] >>> 16) | (v[13] << 48);
+ v[8] = v[8] + v[13];
+ v[7] ^= v[8];
+ v[7] = (v[7] << 1) | (v[7] >>> 63);
+
+ /** G (r, 7, 3, 4, 9, 14); */
+
+ v[3] = v[3] + v[4] + m[sig_g70[r]];
+ v[14] ^= v[3];
+ v[14] = (v[14] << 32) | (v[14] >>> 32);
+ v[9] = v[9] + v[14];
+ v[4] ^= v[9];
+ v[4] = (v[4] >>> 24) | (v[4] << 40);
+ v[3] = v[3] + v[4] + m[sig_g71[r]];
+ v[14] ^= v[3];
+ v[14] = (v[14] >>> 16) | (v[14] << 48);
+ v[9] = v[9] + v[14];
+ v[4] ^= v[9];
+ v[4] = (v[4] << 1) | (v[4] >>> 63);
+ }
+
+ // Update state vector h
+ h[0] ^= v[0] ^ v[8];
+ h[1] ^= v[1] ^ v[9];
+ h[2] ^= v[2] ^ v[10];
+ h[3] ^= v[3] ^ v[11];
+ h[4] ^= v[4] ^ v[12];
+ h[5] ^= v[5] ^ v[13];
+ h[6] ^= v[6] ^ v[14];
+ h[ 7] ^= v[7] ^ v[15];
+
+// Debug.dumpArray("v @ compress end", v);
+// Debug.dumpArray("h @ compress end", h);
+ /* kaamil */
+ }
+
+ ////////////////////////////////////////////////////////////////////////
+ /// Compression Kernel /////////////////////////////////////////// BEGIN
+ ////////////////////////////////////////////////////////////////////////
+
+ /**
+ * a little bit of semantics
+ */
+ interface flag {
+ int last_block = 0;
+ int last_node = 1;
+ }
+
+ ////////////////////////////////////////////////////////////////////////
+ /// Compression Kernel //////////////////////////////////////////// FINI
+ ////////////////////////////////////////////////////////////////////////
+
+ /* TEMP - remove at will */
+ public static class Debug {
+ public static void dumpState (Blake2b.Engine e, final String mark) {
+ System.out.format("-- MARK == @ %s @ ===========\n", mark);
+ dumpArray("register t", e.t);
+ dumpArray("register h", e.h);
+ dumpArray("register f", e.f);
+ dumpArray("register offset", new long[]{e.buflen});
+ System.out.format("-- END MARK =================\n");
+ }
+ public static void dumpArray (final String label, final long[] b) {
+ System.out.format ( "-- %s -- :\n{\n", label );
+ for( int j = 0; j < b.length ; ++j ) {
+ System.out.format ( " [%2d] : %016X\n", j, b[j]);
+ }
+ System.out.format ( "}\n" );
+ }
+ public static void dumpBuffer (final PrintStream out, final String label, final byte[] b) {
+ dumpBuffer(out, label, b, 0, b.length);
+ }
+ public static void dumpBuffer (final PrintStream out, final byte[] b) {
+ dumpBuffer(out, null, b, 0, b.length);
+ }
+ public static void dumpBuffer (final PrintStream out, final byte[] b, final int offset, final int len) {
+ dumpBuffer(out, null, b, offset, len);
+ }
+ public static void dumpBuffer (final PrintStream out, final String label, final byte[] b, final int offset, final int len) {
+ if(label != null)
+ out.format ( "-- %s -- :\n", label );
+ out.format("{\n ", label);
+ for( int j = 0; j < len ; ++j ) {
+ out.format ("%02X", b[j + offset]);
+ if(j+1 < len) {
+ if ((j+1)%8==0) out.print("\n ");
+ else out.print(' ');
+ }
+ }
+ out.format("\n}\n");
+ }
+ }
+ /* TEMP - remove at will */
+
+ // ---------------------------------------------------------------------
+ // Helper for assert error messages
+ // ---------------------------------------------------------------------
+ public static final class Assert {
+ public final static String exclusiveUpperBound = "'%s' %d is >= %d";
+ public final static String inclusiveUpperBound = "'%s' %d is > %d";
+ public final static String exclusiveLowerBound = "'%s' %d is <= %d";
+ public final static String inclusiveLowerBound = "'%s' %d is < %d";
+ static String assertFail(final String name, final T v, final String err, final T spec) {
+ new Exception().printStackTrace();
+ return String.format(err, name, v, spec);
+ }
+ }
+ // ---------------------------------------------------------------------
+ // Little Endian Codecs (inlined in the compressor)
+ /*
+ * impl note: these are not library funcs and used in hot loops, so no
+ * null or bounds checks are performed. For our purposes, this is OK.
+ */
+ // ---------------------------------------------------------------------
+
+ public static class LittleEndian {
+ private static final byte[] hex_digits = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'};
+ private static final byte[] HEX_digits = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'};
+ /** @return hex rep of byte (lower case). */
+ static public String toHexStr (final byte[] b) {
+ return toHexStr (b, false); // because String class is slower.
+ }
+ static public String toHexStr (final byte[] b, boolean upperCase) {
+ final int len = b.length;
+ final byte[] digits = new byte[ len * 2 ];
+ final byte[] hex_rep = upperCase ? HEX_digits : hex_digits ;
+ for (int i = 0; i < len; i++) {
+ digits [ i*2 ] = hex_rep [ (byte) (b[i] >> 4 & 0x0F) ];
+ digits [ i*2+1 ] = hex_rep [ (byte) (b[i] & 0x0F) ];
+ }
+ return new String(digits);
+ }
+ public static int readInt (final byte[] b, int off) {
+ int v0
+ = ((int)b [ off++ ] & 0xFF );
+ v0 |= ((int)b [ off++ ] & 0xFF ) << 8;
+ v0 |= ((int)b [ off++ ] & 0xFF ) << 16;
+ v0 |= ((int)b [ off ] ) << 24;
+ return v0;
+ }
+ /** Little endian - byte[] to long */
+ public static long readLong (final byte[] b, int off) {
+ long v0
+ = ((long)b [ off++ ] & 0xFF );
+ v0 |= ((long)b [ off++ ] & 0xFF ) << 8;
+ v0 |= ((long)b [ off++ ] & 0xFF ) << 16;
+ v0 |= ((long)b [ off++ ] & 0xFF ) << 24;
+ v0 |= ((long)b [ off++ ] & 0xFF ) << 32;
+ v0 |= ((long)b [ off++ ] & 0xFF ) << 40;
+ v0 |= ((long)b [ off++ ] & 0xFF ) << 48;
+ v0 |= ((long)b [ off ] ) << 56;
+ return v0;
+ }
+ /** */
+ /** Little endian - long to byte[] */
+ public static void writeLong (long v, final byte[] b, final int off) {
+ b [ off ] = (byte) v; v >>>= 8;
+ b [ off + 1 ] = (byte) v; v >>>= 8;
+ b [ off + 2 ] = (byte) v; v >>>= 8;
+ b [ off + 3 ] = (byte) v; v >>>= 8;
+ b [ off + 4 ] = (byte) v; v >>>= 8;
+ b [ off + 5 ] = (byte) v; v >>>= 8;
+ b [ off + 6 ] = (byte) v; v >>>= 8;
+ b [ off + 7 ] = (byte) v;
+ }
+ /** Little endian - int to byte[] */
+ public static void writeInt (int v, final byte[] b, final int off) {
+ b [ off ] = (byte) v; v >>>= 8;
+ b [ off + 1 ] = (byte) v; v >>>= 8;
+ b [ off + 2 ] = (byte) v; v >>>= 8;
+ b [ off + 3 ] = (byte) v;
+ }
+ }
+ }
+ // ---------------------------------------------------------------------
+ // digest parameter (block)
+ // ---------------------------------------------------------------------
+ /** Blake2b configuration parameters block per spec */
+ // REVU: need to review a revert back to non-lazy impl TODO: do & bench
+ public static class Param implements AlgorithmParameterSpec {
+ /**
+ * default bytes of Blake2b parameter block
+ */
+ final static byte[] default_bytes = new byte[Spec.param_bytes];
+ /**
+ * default Blake2b h vector
+ */
+ final static long[] default_h = new long[Spec.state_space_len ];
+
+ /** initialize default_bytes */
+ static {
+ default_bytes [ Xoff.digest_length ] = Default.digest_length;
+ default_bytes [ Xoff.key_length ] = Default.key_length;
+ default_bytes [ Xoff.fanout ] = Default.fanout;
+ default_bytes [ Xoff.depth ] = Default.depth;
+ /* def. leaf_length is 0 fill and already set by new byte[] */
+ /* def. node_offset is 0 fill and already set by new byte[] */
+ default_bytes [ Xoff.node_depth ] = Default.node_depth;
+ default_bytes [ Xoff.inner_length] = Default.inner_length;
+ /* def. salt is 0 fill and already set by new byte[] */
+ /* def. personal is 0 fill and already set by new byte[] */
+ }
+
+ static {
+ default_h [0] = readLong( default_bytes, 0 );
+ default_h [1] = readLong( default_bytes, 8 );
+ default_h [2] = readLong( default_bytes, 16 );
+ default_h [3] = readLong( default_bytes, 24 );
+ default_h [4] = readLong( default_bytes, 32 );
+ default_h [5] = readLong( default_bytes, 40 );
+ default_h [6] = readLong( default_bytes, 48 );
+ default_h [7] = readLong( default_bytes, 56 );
+
+ default_h[0] ^= Spec.IV[0];
+ default_h[1] ^= Spec.IV[1];
+ default_h[2] ^= Spec.IV[2];
+ default_h[3] ^= Spec.IV[3];
+ default_h[4] ^= Spec.IV[4];
+ default_h[5] ^= Spec.IV[5];
+ default_h[6] ^= Spec.IV[6];
+ default_h[7] ^= Spec.IV[7];
+ }
+
+ /** */
+ private final long[] h = new long [ Spec.state_space_len ];
+ /** */
+ private boolean hasKey = false;
+ /** not sure how to make this secure - TODO */
+ private byte[] key_bytes = null;
+ /** */
+ private byte[] bytes = null;
+ /** */
+ public Param() {
+ System.arraycopy( default_h, 0, h, 0, Spec.state_space_len );
+ }
+
+ /** */
+ public long[] initialized_H () {
+ return h;
+ }
+
+ /** package only - copy returned - do not use in functional loops */
+ public byte[] getBytes() {
+ lazyInitBytes();
+ byte[] copy = new byte[ bytes.length ];
+ System.arraycopy( bytes, 0, copy, 0, bytes.length );
+ return copy;
+ }
+
+ final byte getByteParam (final int xoffset) {
+ byte[] _bytes = bytes;
+ if(_bytes == null) _bytes = Param.default_bytes;
+ return _bytes[ xoffset];
+ }
+
+ final int getIntParam (final int xoffset) {
+ byte[] _bytes = bytes;
+ if(_bytes == null) _bytes = Param.default_bytes;
+ return readInt ( _bytes, xoffset);
+ }
+
+ final long getLongParam (final int xoffset) {
+ byte[] _bytes = bytes;
+ if(_bytes == null) _bytes = Param.default_bytes;
+ return readLong ( _bytes, xoffset);
+ }
+
+ // TODO same for tree params depth, fanout, inner, node-depth, node-offset
+ public final int getDigestLength() {
+ return (int) getByteParam ( Xoff.digest_length );
+ }
+
+ /* 0-7 inclusive */
+ public final Param setDigestLength(int len) {
+ assert len > 0 : assertFail("len", len, exclusiveLowerBound, 0);
+ assert len <= Spec.max_digest_bytes : assertFail("len", len, inclusiveUpperBound, Spec.max_digest_bytes);
+
+ lazyInitBytes();
+ bytes[Xoff.digest_length] = (byte) len;
+ h[0] = readLong(bytes, 0);
+ h[0] ^= Spec.IV[0];
+ return this;
+ }
+
+ public final int getKeyLength() {
+ return (int) getByteParam(Xoff.key_length);
+ }
+
+ public final int getFanout() {
+ return (int) getByteParam(Xoff.fanout);
+ }
+
+ public final Param setFanout(int fanout) {
+ assert fanout > 0 : assertFail("fanout", fanout, exclusiveLowerBound, 0);
+
+ lazyInitBytes();
+ bytes[Xoff.fanout] = (byte) fanout;
+ h[0] = readLong(bytes, 0);
+ h[0] ^= Spec.IV[0];
+ return this;
+ }
+
+ public final int getDepth() {
+ return (int) getByteParam(Xoff.depth);
+ }
+
+ public final Param setDepth(int depth) {
+ assert depth > 0 : assertFail("depth", depth, exclusiveLowerBound, 0);
+
+ lazyInitBytes();
+ bytes[Xoff.depth] = (byte) depth;
+ h[0] = readLong(bytes, 0);
+ h[0] ^= Spec.IV[0];
+ return this;
+ }
+
+ public final int getLeafLength() {
+ return getIntParam(Xoff.leaf_length);
+ }
+
+ public final Param setLeafLength(int leaf_length) {
+ assert leaf_length >= 0 : assertFail("leaf_length", leaf_length, inclusiveLowerBound, 0);
+
+ lazyInitBytes();
+ writeInt(leaf_length, bytes, Xoff.leaf_length);
+ h[0] = readLong(bytes, 0);
+ h[0] ^= Spec.IV[0];
+ return this;
+ }
+
+ public final long getNodeOffset() {
+ return getLongParam ( Xoff.node_offset);
+ }
+
+ /* 8-15 inclusive */
+ public final Param setNodeOffset(long node_offset) {
+ assert node_offset >= 0 : assertFail("node_offset", node_offset, inclusiveLowerBound, 0);
+
+ lazyInitBytes();
+ writeLong(node_offset, bytes, Xoff.node_offset);
+ h[1] = readLong(bytes, Xoff.node_offset);
+ h[1] ^= Spec.IV[1];
+ return this;
+ }
+
+ public final int getNodeDepth() {
+ return (int) getByteParam(Xoff.node_depth);
+ }
+
+ /* 16-23 inclusive */
+ public final Param setNodeDepth(int node_depth) {
+ assert node_depth >= 0 : assertFail("node_depth", node_depth, inclusiveLowerBound, 0);
+
+ lazyInitBytes();
+ bytes[Xoff.node_depth] = (byte) node_depth;
+ h[2] = readLong(bytes, Xoff.node_depth);
+ h[2] ^= Spec.IV[2];
+ h[3] = readLong(bytes, Xoff.node_depth + 8);
+ h[3] ^= Spec.IV[3];
+ return this;
+ }
+
+ public final int getInnerLength() {
+ return (int) getByteParam(Xoff.inner_length );
+ }
+
+ public final Param setInnerLength(int inner_length) {
+ assert inner_length >= 0 : assertFail("inner_length", inner_length, inclusiveLowerBound, 0);
+
+ lazyInitBytes();
+ bytes[Xoff.inner_length] = (byte) inner_length;
+ h[2] = readLong(bytes, Xoff.node_depth);
+ h[2] ^= Spec.IV[2];
+ h[3] = readLong(bytes, Xoff.node_depth + 8);
+ h[3] ^= Spec.IV[3];
+ return this;
+ }
+
+ public final boolean hasKey() {
+ return this.hasKey;
+ }
+
+ @Override
+ public Param clone() {
+ final Param clone = new Param();
+ System.arraycopy(this.h, 0, clone.h, 0, h.length);
+ clone.lazyInitBytes();
+ System.arraycopy(this.bytes, 0, clone.bytes, 0, this.bytes.length);
+
+ if (this.hasKey) {
+ clone.hasKey = this.hasKey;
+ clone.key_bytes = new byte[Spec.max_key_bytes * 2];
+ System.arraycopy(this.key_bytes, 0, clone.key_bytes, 0, this.key_bytes.length);
+ }
+ return clone;
+ }
+
+ ////////////////////////////////////////////////////////////////////////
+ /// lazy setters - write directly to the bytes image of param block ////
+ ////////////////////////////////////////////////////////////////////////
+ final void lazyInitBytes() {
+ if (bytes == null) {
+ bytes = new byte[Spec.param_bytes];
+ System.arraycopy(Param.default_bytes, 0, bytes, 0, Spec.param_bytes);
+ }
+ }
+
+ public final Param setKey(final Key key) {
+ assert key != null : "key is null";
+ final byte[] keybytes = key.getEncoded();
+ assert keybytes != null : "key.encoded() is null";
+
+ return this.setKey(keybytes);
+ }
+
+ public final Param setKey(final byte[] key) {
+ assert key != null : "key is null";
+ assert key.length >= 0 : assertFail("key.length", key.length, inclusiveUpperBound, 0);
+ assert key.length <= Spec.max_key_bytes : assertFail("key.length", key.length, inclusiveUpperBound, Spec.max_key_bytes);
+
+ // zeropad keybytes
+ this.key_bytes = new byte[Spec.max_key_bytes * 2];
+ System.arraycopy(key, 0, this.key_bytes, 0, key.length);
+ lazyInitBytes();
+ bytes[Xoff.key_length] = (byte) key.length; // checked c ref; this is correct
+ h[0] = readLong(bytes, 0);
+ h[0] ^= Spec.IV[0];
+ this.hasKey = true;
+ return this;
+ }
+
+ /* 32-47 inclusive */
+ public final Param setSalt(final byte[] salt) {
+ assert salt != null : "salt is null";
+ assert salt.length <= Spec.max_salt_bytes : assertFail("salt.length", salt.length, inclusiveUpperBound, Spec.max_salt_bytes);
+
+ lazyInitBytes();
+ Arrays.fill ( bytes, Xoff.salt, Xoff.salt + Spec.max_salt_bytes, (byte)0);
+ System.arraycopy( salt, 0, bytes, Xoff.salt, salt.length );
+ h[ 4 ] = readLong( bytes, Xoff.salt );
+ h[ 4 ] ^= Spec.IV [ 4 ];
+ h[ 5 ] = readLong( bytes, Xoff.salt + 8 );
+ h[ 5 ] ^= Spec.IV [ 5 ];
+ return this;
+ }
+
+ /* 48-63 inclusive */
+ public final Param setPersonal(byte[] personal) {
+ assert personal != null : "personal is null";
+ assert personal.length <= Spec.max_personalization_bytes : assertFail("personal.length", personal.length, inclusiveUpperBound, Spec.max_personalization_bytes);
+
+ lazyInitBytes();
+ Arrays.fill(bytes, Xoff.personal, Xoff.personal + Spec.max_personalization_bytes, (byte) 0);
+ System.arraycopy(personal, 0, bytes, Xoff.personal, personal.length);
+ h[6] = readLong(bytes, Xoff.personal);
+ h[6] ^= Spec.IV[6];
+ h[7] = readLong(bytes, Xoff.personal + 8);
+ h[7] ^= Spec.IV[7];
+ return this;
+ }
+
+ /* 24-31 masked by reserved and remain unchanged */
+
+ interface Xoff {
+ int digest_length = 0;
+ int key_length = 1;
+ int fanout = 2;
+ int depth = 3;
+ int leaf_length = 4;
+ int node_offset = 8;
+ int node_depth = 16;
+ int inner_length = 17;
+ int reserved = 18;
+ int salt = 32;
+ int personal = 48;
+ }
+
+ public interface Default {
+ byte digest_length = Spec.max_digest_bytes;
+ byte key_length = 0;
+ byte fanout = 1;
+ byte depth = 1;
+ int leaf_length = 0;
+ long node_offset = 0;
+ byte node_depth = 0;
+ byte inner_length = 0;
+ }
+ ////////////////////////////////////////////////////////////////////////
+ /// lazy setters /////////////////////////////////////////////////// END
+ ////////////////////////////////////////////////////////////////////////
+ }
+}
diff --git a/src/ext/plantuml/com/at/gadermaier/argon2/exception/Argon2Exception.java b/src/ext/plantuml/com/at/gadermaier/argon2/exception/Argon2Exception.java
new file mode 100644
index 000000000..6e1b677d5
--- /dev/null
+++ b/src/ext/plantuml/com/at/gadermaier/argon2/exception/Argon2Exception.java
@@ -0,0 +1,13 @@
+/* This file is taken from
+ https://github.com/andreas1327250/argon2-java
+
+ Original Author: Andreas Gadermaier
+ */
+package ext.plantuml.com.at.gadermaier.argon2.exception;
+
+/* dislike checked exceptions */
+class Argon2Exception extends RuntimeException {
+ Argon2Exception(String message) {
+ super(message);
+ }
+}
diff --git a/src/ext/plantuml/com/at/gadermaier/argon2/exception/Argon2InvalidParameterException.java b/src/ext/plantuml/com/at/gadermaier/argon2/exception/Argon2InvalidParameterException.java
new file mode 100644
index 000000000..6a6678972
--- /dev/null
+++ b/src/ext/plantuml/com/at/gadermaier/argon2/exception/Argon2InvalidParameterException.java
@@ -0,0 +1,12 @@
+/* This file is taken from
+ https://github.com/andreas1327250/argon2-java
+
+ Original Author: Andreas Gadermaier
+ */
+package ext.plantuml.com.at.gadermaier.argon2.exception;
+
+public class Argon2InvalidParameterException extends Argon2Exception{
+ public Argon2InvalidParameterException(String message) {
+ super(message);
+ }
+}
diff --git a/src/ext/plantuml/com/at/gadermaier/argon2/model/Argon2Type.java b/src/ext/plantuml/com/at/gadermaier/argon2/model/Argon2Type.java
new file mode 100644
index 000000000..546051a16
--- /dev/null
+++ b/src/ext/plantuml/com/at/gadermaier/argon2/model/Argon2Type.java
@@ -0,0 +1,10 @@
+/* This file is taken from
+ https://github.com/andreas1327250/argon2-java
+
+ Original Author: Andreas Gadermaier
+ */
+package ext.plantuml.com.at.gadermaier.argon2.model;
+
+public enum Argon2Type {
+ Argon2d, Argon2i, Argon2id;
+}
diff --git a/src/ext/plantuml/com/at/gadermaier/argon2/model/Block.java b/src/ext/plantuml/com/at/gadermaier/argon2/model/Block.java
new file mode 100644
index 000000000..a7418dd9d
--- /dev/null
+++ b/src/ext/plantuml/com/at/gadermaier/argon2/model/Block.java
@@ -0,0 +1,81 @@
+/* This file is taken from
+ https://github.com/andreas1327250/argon2-java
+
+ Original Author: Andreas Gadermaier
+ */
+package ext.plantuml.com.at.gadermaier.argon2.model;
+
+
+import static ext.plantuml.com.at.gadermaier.argon2.Constants.ARGON2_BLOCK_SIZE;
+import static ext.plantuml.com.at.gadermaier.argon2.Constants.ARGON2_QWORDS_IN_BLOCK;
+
+import java.util.Arrays;
+
+import ext.plantuml.com.at.gadermaier.argon2.Util;
+
+public class Block {
+
+ /* 128 * 8 Byte QWords */
+ public long[] v;
+
+ public Block() {
+ v = new long[ARGON2_QWORDS_IN_BLOCK];
+ }
+
+ public void fromBytes(byte[] input) {
+ assert (input.length == ARGON2_BLOCK_SIZE);
+
+ for (int i = 0; i < v.length; i++) {
+ byte[] slice = Arrays.copyOfRange(input, i * 8, (i + 1) * 8);
+ v[i] = Util.littleEndianBytesToLong(slice);
+ }
+ }
+
+ public byte[] toBytes() {
+ byte[] result = new byte[ARGON2_BLOCK_SIZE];
+
+ for (int i = 0; i < v.length; i++) {
+ byte[] bytes = Util.longToLittleEndianBytes(v[i]);
+ System.arraycopy(bytes, 0, result, i * bytes.length, bytes.length);
+ }
+
+ return result;
+ }
+
+ public void copyBlock(Block other) {
+ System.arraycopy(other.v, 0, v, 0, v.length);
+ }
+
+ public void xor(Block b1, Block b2) {
+ for (int i = 0; i < v.length; i++) {
+ v[i] = b1.v[i] ^ b2.v[i];
+ }
+ }
+
+ public void xor(Block b1, Block b2, Block b3) {
+ for (int i = 0; i < v.length; i++) {
+ v[i] = b1.v[i] ^ b2.v[i] ^ b3.v[i];
+ }
+ }
+
+ public void xorWith(Block other) {
+ for (int i = 0; i < v.length; i++) {
+ v[i] = v[i] ^ other.v[i];
+ }
+ }
+
+ @Override
+ public String toString() {
+ StringBuilder result = new StringBuilder();
+ for (long value : v) {
+ result.append(Util.bytesToHexString(Util.longToLittleEndianBytes(value)));
+ }
+
+ return result.toString();
+ }
+
+ void clear() {
+ Arrays.fill(v, 0);
+ }
+}
+
diff --git a/src/ext/plantuml/com/at/gadermaier/argon2/model/Instance.java b/src/ext/plantuml/com/at/gadermaier/argon2/model/Instance.java
new file mode 100644
index 000000000..807654466
--- /dev/null
+++ b/src/ext/plantuml/com/at/gadermaier/argon2/model/Instance.java
@@ -0,0 +1,88 @@
+/* This file is taken from
+ https://github.com/andreas1327250/argon2-java
+
+ Original Author: Andreas Gadermaier
+ */
+package ext.plantuml.com.at.gadermaier.argon2.model;
+
+import static ext.plantuml.com.at.gadermaier.argon2.Constants.ARGON2_SYNC_POINTS;
+
+import ext.plantuml.com.at.gadermaier.argon2.Argon2;
+
+public class Instance {
+
+ public Block[] memory;
+ private int version;
+ private int iterations;
+ private int segmentLength;
+ private int laneLength;
+ private int lanes;
+
+ private Argon2Type type;
+
+ public Instance(Argon2 argon2) {
+ this.version = argon2.getVersion();
+ this.iterations = argon2.getIterations();
+ this.lanes = argon2.getLanes();
+ this.type = argon2.getType();
+
+ /* 2. Align memory size */
+ /* Minimum memoryBlocks = 8L blocks, where L is the number of lanes */
+ int memoryBlocks = argon2.getMemory();
+
+ if (memoryBlocks < 2 * ARGON2_SYNC_POINTS * argon2.getLanes()) {
+ memoryBlocks = 2 * ARGON2_SYNC_POINTS * argon2.getLanes();
+ }
+
+ this.segmentLength = memoryBlocks / (argon2.getLanes() * ARGON2_SYNC_POINTS);
+ this.laneLength = segmentLength * ARGON2_SYNC_POINTS;
+ /* Ensure that all segments have equal length */
+ memoryBlocks = segmentLength * (argon2.getLanes() * ARGON2_SYNC_POINTS);
+
+ initMemory(memoryBlocks);
+ }
+
+ private void initMemory(int memoryBlocks) {
+ this.memory = new Block[memoryBlocks];
+
+ for (int i = 0; i < memory.length; i++) {
+ memory[i] = new Block();
+ }
+ }
+
+ public void clear() {
+ for (Block b : memory) {
+ b.clear();
+ }
+
+ memory = null;
+ }
+
+ public Block[] getMemory() {
+ return memory;
+ }
+
+ public int getVersion() {
+ return version;
+ }
+
+ public int getIterations() {
+ return iterations;
+ }
+
+ public int getSegmentLength() {
+ return segmentLength;
+ }
+
+ public int getLaneLength() {
+ return laneLength;
+ }
+
+ public int getLanes() {
+ return lanes;
+ }
+
+ public Argon2Type getType() {
+ return type;
+ }
+}
diff --git a/src/ext/plantuml/com/at/gadermaier/argon2/model/Position.java b/src/ext/plantuml/com/at/gadermaier/argon2/model/Position.java
new file mode 100644
index 000000000..bf052ba3e
--- /dev/null
+++ b/src/ext/plantuml/com/at/gadermaier/argon2/model/Position.java
@@ -0,0 +1,22 @@
+/* This file is taken from
+ https://github.com/andreas1327250/argon2-java
+
+ Original Author: Andreas Gadermaier
+ */
+package ext.plantuml.com.at.gadermaier.argon2.model;
+
+public class Position {
+
+ public int pass;
+ public int lane;
+ public int slice;
+ public int index;
+
+ public Position(int pass, int lane, int slice, int index) {
+ this.pass = pass;
+ this.lane = lane;
+ this.slice = slice;
+ this.index = index;
+ }
+}
+
diff --git a/src/net/sourceforge/plantuml/dedication/0.png b/src/net/sourceforge/plantuml/dedication/0.png
deleted file mode 100644
index a03ee156b..000000000
Binary files a/src/net/sourceforge/plantuml/dedication/0.png and /dev/null differ
diff --git a/src/net/sourceforge/plantuml/dedication/1.png b/src/net/sourceforge/plantuml/dedication/1.png
deleted file mode 100644
index 91edd9a89..000000000
Binary files a/src/net/sourceforge/plantuml/dedication/1.png and /dev/null differ
diff --git a/src/net/sourceforge/plantuml/dedication/2.png b/src/net/sourceforge/plantuml/dedication/2.png
deleted file mode 100644
index c37934ee8..000000000
Binary files a/src/net/sourceforge/plantuml/dedication/2.png and /dev/null differ
diff --git a/src/net/sourceforge/plantuml/dedication/514816d583044efbd336882227deb822194ff63e3bdc3cf707a01f17770d5a6a.png b/src/net/sourceforge/plantuml/dedication/514816d583044efbd336882227deb822194ff63e3bdc3cf707a01f17770d5a6a.png
new file mode 100644
index 000000000..8bf20e266
Binary files /dev/null and b/src/net/sourceforge/plantuml/dedication/514816d583044efbd336882227deb822194ff63e3bdc3cf707a01f17770d5a6a.png differ
diff --git a/src/net/sourceforge/plantuml/dedication/835ff5d643b58cd35a20db6480071d05751aa6a0e01da78662ceafd0161f3f5e.png b/src/net/sourceforge/plantuml/dedication/835ff5d643b58cd35a20db6480071d05751aa6a0e01da78662ceafd0161f3f5e.png
new file mode 100644
index 000000000..85c96fb5b
Binary files /dev/null and b/src/net/sourceforge/plantuml/dedication/835ff5d643b58cd35a20db6480071d05751aa6a0e01da78662ceafd0161f3f5e.png differ
diff --git a/src/net/sourceforge/plantuml/dedication/DecoderInputStream.java b/src/net/sourceforge/plantuml/dedication/DecoderInputStream.java
deleted file mode 100644
index 0b572230f..000000000
--- a/src/net/sourceforge/plantuml/dedication/DecoderInputStream.java
+++ /dev/null
@@ -1,104 +0,0 @@
-/* ========================================================================
- * PlantUML : a free UML diagram generator
- * ========================================================================
- *
- * (C) Copyright 2009-2020, Arnaud Roques
- *
- * Project Info: http://plantuml.com
- *
- * If you like this project or if you find it useful, you can support us at:
- *
- * http://plantuml.com/patreon (only 1$ per month!)
- * http://plantuml.com/paypal
- *
- * This file is part of PlantUML.
- *
- * PlantUML is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * PlantUML distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
- * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
- * License for more details.
- *
- * You should have received a copy of the GNU General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
- * USA.
- *
- *
- * Original Author: Arnaud Roques
- *
- *
- */
-package net.sourceforge.plantuml.dedication;
-
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.UnsupportedEncodingException;
-import java.security.MessageDigest;
-import java.security.NoSuchAlgorithmException;
-import java.util.Random;
-
-public class DecoderInputStream extends InputStream {
-
- private final TurningBytes message;
- private final TurningBytes sha;
- private final Random rnd;
- private final InputStream source;
-
- public DecoderInputStream(InputStream source, String s) {
- this.source = source;
- try {
- final byte[] text = s.getBytes("UTF-8");
- final byte[] key = getSignatureSha512(text);
- this.rnd = new Random(getSeed(key));
- this.message = new TurningBytes(text);
- this.sha = new TurningBytes(key);
- } catch (UnsupportedEncodingException e) {
- e.printStackTrace();
- throw new UnsupportedOperationException(e);
- }
- }
-
- private static byte[] getSignatureSha512(byte[] bytes) {
- try {
- final MessageDigest msgDigest = MessageDigest.getInstance("SHA-512");
- msgDigest.update(bytes);
- return msgDigest.digest();
- } catch (NoSuchAlgorithmException e) {
- e.printStackTrace();
- throw new UnsupportedOperationException(e);
- }
- }
-
- private long getSeed(byte[] bytes) {
- long result = 17;
- for (byte b : bytes) {
- result = result * 37 + b;
- }
- return result;
- }
-
- private byte getNextByte() {
- return (byte) (rnd.nextInt() ^ message.nextByte() ^ sha.nextByte());
- }
-
- @Override
- public void close() throws IOException {
- source.close();
- }
-
- @Override
- public int read() throws IOException {
- int b = source.read();
- if (b == -1) {
- return -1;
- }
- b = (b ^ getNextByte()) & 0xFF;
- return b;
- }
-
-}
diff --git a/src/net/sourceforge/plantuml/dedication/Dedication.java b/src/net/sourceforge/plantuml/dedication/Dedication.java
index c272d6e3a..a8686c273 100644
--- a/src/net/sourceforge/plantuml/dedication/Dedication.java
+++ b/src/net/sourceforge/plantuml/dedication/Dedication.java
@@ -36,69 +36,16 @@
package net.sourceforge.plantuml.dedication;
import java.awt.image.BufferedImage;
-import java.io.ByteArrayInputStream;
-import java.io.ByteArrayOutputStream;
-import java.io.IOException;
-import java.io.InputStream;
-import java.lang.reflect.Method;
import java.math.BigInteger;
-import javax.imageio.stream.ImageInputStream;
+public interface Dedication {
-import net.sourceforge.plantuml.security.ImageIO;
-
-public class Dedication {
-
- private final String name;
public static final int SIZE = 512;
- public Dedication(String name) {
- this.name = name;
- }
-
static public final BigInteger E = new BigInteger("47");
static public final BigInteger N = new BigInteger(
"64194259632025692228025828504368542164501926620236990850309916606915924860847417702229807236946186163298479808527077315212362810246237044147835839820235668271044023359607622658694578433933680627840319408427732468918341837133798296090069295727323673222224923200718714534955390633175683720810506099934813509605263799234445827953809462431871169282281822048299576307847441008670575692934434087522877910989584374673170522742162366773143807761599862833698229067475807108264396251702152180676841544743258182370105404479387062985271422237607462447989728490398294623785717593446941673706569352249533885603771123718557406286501161336667835919957553680522213067630956498293529840163155604109185561515875171125161872265975088797712442352939352686113608345330266855433849127812528823634773975825170679786399199082599910532761710473383280738663105826045325480095451410448217715495894688594898541182351588505292424154550388343455540760277051977859647543838445735549451966254020972172982014944475678385523833120793348365125754234511467512831686599126674298367512469557219326026525667529348508876650236597163509336304607610284488623800062157659286940214435134423619711736992281071131245654755167288438258292694799131521268600284444731890784171372171309");
- public InputStream getInputStream(String keepLetter) throws IOException {
- final InputStream tmp = PSystemDedication.class.getResourceAsStream(name + ".png");
- final InputStream step1 = new DecoderInputStream(tmp, keepLetter);
- final QBlocks rsa = QBlocks.readFrom(step1, SIZE + 1);
- final QBlocks decrypted = rsa.change(E, N);
- ByteArrayOutputStream baos = new ByteArrayOutputStream();
- decrypted.writeTo(baos, SIZE);
- baos.close();
- return new ByteArrayInputStream(baos.toByteArray());
- }
-
- public static BufferedImage getBufferedImage(InputStream is) {
- try {
- final Class> clVP8Decoder = Class.forName("net.sourceforge.plantuml.webp.VP8Decoder");
- final Object vp8Decoder = clVP8Decoder.newInstance();
- // final VP8Decoder vp8Decoder = new VP8Decoder();
- final Method decodeFrame = clVP8Decoder.getMethod("decodeFrame", ImageInputStream.class);
- final ImageInputStream iis = ImageIO.createImageInputStream(is);
- decodeFrame.invoke(vp8Decoder, iis);
- // vp8Decoder.decodeFrame(iis);
- iis.close();
- final Object frame = clVP8Decoder.getMethod("getFrame").invoke(vp8Decoder);
- return (BufferedImage) frame.getClass().getMethod("getBufferedImage").invoke(frame);
- // final VP8Frame frame = vp8Decoder.getFrame();
- // return frame.getBufferedImage();
- } catch (Exception e) {
- e.printStackTrace();
- return null;
- }
- }
-
- public BufferedImage getBufferedImage(String keepLetter) {
- try {
- final InputStream is = getInputStream(keepLetter);
- return getBufferedImage(is);
- } catch (Exception e) {
- e.printStackTrace();
- return null;
- }
- }
+ public BufferedImage getImage(String sentence);
}
diff --git a/src/net/sourceforge/plantuml/dedication/DedicationCrypted.java b/src/net/sourceforge/plantuml/dedication/DedicationCrypted.java
new file mode 100644
index 000000000..9681d410e
--- /dev/null
+++ b/src/net/sourceforge/plantuml/dedication/DedicationCrypted.java
@@ -0,0 +1,119 @@
+/* ========================================================================
+ * PlantUML : a free UML diagram generator
+ * ========================================================================
+ *
+ * (C) Copyright 2009-2020, Arnaud Roques
+ *
+ * Project Info: http://plantuml.com
+ *
+ * If you like this project or if you find it useful, you can support us at:
+ *
+ * http://plantuml.com/patreon (only 1$ per month!)
+ * http://plantuml.com/paypal
+ *
+ * This file is part of PlantUML.
+ *
+ * PlantUML is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * PlantUML distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
+ * License for more details.
+ *
+ * You should have received a copy of the GNU General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
+ * USA.
+ *
+ *
+ * Original Author: Arnaud Roques
+ *
+ *
+ */
+package net.sourceforge.plantuml.dedication;
+
+import java.awt.image.BufferedImage;
+import java.io.ByteArrayInputStream;
+import java.math.BigInteger;
+
+import net.sourceforge.plantuml.utils.MTRandom;
+
+public class DedicationCrypted implements Dedication {
+
+ private final String argon2;
+ private final BigInteger pq;
+ private final byte crypted[];
+ private final int tinyHash;
+ private String solution;
+
+ private long next = 0L;
+
+ public DedicationCrypted(byte crypted[], int tinyHash, String argon2, BigInteger pq) {
+ this.crypted = crypted;
+ this.pq = pq;
+ this.argon2 = argon2;
+ this.tinyHash = tinyHash;
+ }
+
+ public synchronized BufferedImage getImage(final String sentence) {
+ if (sentence.length() < 40) {
+ return null;
+ }
+
+ try {
+ if (solution == null || sentence.equals(this.solution) == false) {
+ if (System.currentTimeMillis() < next) {
+ return null;
+ }
+ final int tinyHash = Noise.shortHash(sentence.getBytes("UTF-8"), N.toByteArray());
+ if (this.tinyHash != tinyHash) {
+ return null;
+ }
+ this.next = System.currentTimeMillis() + 5000L;
+ }
+
+ final byte[] hash1 = Noise.computeArgon2bytes(sentence.getBytes("UTF-8"),
+ (pq.toString(35) + sentence).getBytes("UTF-8"));
+ final byte[] hash2 = Noise.computeArgon2bytes(sentence.getBytes("UTF-8"),
+ (pq.toString(36) + sentence).getBytes("UTF-8"));
+
+ final BlumBlumShub rndBBS = new BlumBlumShub(pq, hash1);
+ final MTRandom rndMT = new MTRandom(hash2);
+
+ byte[] current = crypted.clone();
+ Noise.shuffle(current, rndMT);
+ Noise.xor(current, rndBBS);
+ Noise.xor(current, sentence.getBytes("UTF-8"));
+
+ Noise.shuffle(current, rndMT);
+
+ final RBlocks init = RBlocks.readFrom(current, 513);
+ final RBlocks decoded = init.change(E, N);
+
+ current = decoded.toByteArray(512);
+
+ Noise.shuffle(current, rndMT);
+ Noise.xor(current, rndBBS);
+
+ final String argon = Noise.computeArgon2String(current, (pq.toString(34) + sentence).getBytes("UTF-8"));
+
+ if (this.argon2.equals(argon) == false) {
+ return null;
+ }
+ Noise.shuffle(current, rndMT);
+ current = Noise.reverse(current, rndMT.nextInt());
+
+ final BufferedImage img = PSystemDedication.getBufferedImage(new ByteArrayInputStream(current));
+ this.solution = sentence;
+ return img;
+ } catch (Throwable t) {
+ t.printStackTrace();
+ return null;
+ }
+
+ }
+
+}
diff --git a/src/net/sourceforge/plantuml/dedication/NoisyInputStream.java b/src/net/sourceforge/plantuml/dedication/DedicationSimple.java
similarity index 58%
rename from src/net/sourceforge/plantuml/dedication/NoisyInputStream.java
rename to src/net/sourceforge/plantuml/dedication/DedicationSimple.java
index d99a894eb..3b0056d03 100644
--- a/src/net/sourceforge/plantuml/dedication/NoisyInputStream.java
+++ b/src/net/sourceforge/plantuml/dedication/DedicationSimple.java
@@ -35,38 +35,41 @@
*/
package net.sourceforge.plantuml.dedication;
-import java.io.IOException;
-import java.io.InputStream;
+import java.awt.image.BufferedImage;
+import java.io.ByteArrayInputStream;
-import net.sourceforge.plantuml.utils.MTRandom;
+public class DedicationSimple implements Dedication {
-public class NoisyInputStream extends InputStream {
+ private final byte crypted[];
+ private final String sentence;
- private final MTRandom rnd;
- private final InputStream source;
-
- public NoisyInputStream(InputStream source, byte[] pass) {
- this.source = source;
- this.rnd = new MTRandom(pass);
+ public DedicationSimple(byte crypted[], String sentence) {
+ this.crypted = crypted;
+ this.sentence = sentence;
}
- private byte getNextByte() {
- return (byte) rnd.nextInt();
- }
-
- @Override
- public void close() throws IOException {
- source.close();
- }
-
- @Override
- public int read() throws IOException {
- int b = source.read();
- if (b == -1) {
- return -1;
+ public synchronized BufferedImage getImage(String sentence) {
+ if (same(this.sentence, sentence) == false) {
+ return null;
}
- b = (b ^ getNextByte()) & 0xFF;
- return b;
+
+ try {
+ byte[] current = crypted.clone();
+
+ final RBlocks init = RBlocks.readFrom(current, 513);
+ final RBlocks decoded = init.change(E, N);
+ current = decoded.toByteArray(512);
+ return PSystemDedication.getBufferedImage(new ByteArrayInputStream(current));
+ } catch (Throwable t) {
+ t.printStackTrace();
+ return null;
+ }
+ }
+
+ private boolean same(String s1, String s2) {
+ s1 = s1.replaceAll("[^\\p{L}0-9]+", "");
+ s2 = s2.replaceAll("[^\\p{L}0-9]+", "");
+ return s1.equalsIgnoreCase(s2);
}
}
diff --git a/src/net/sourceforge/plantuml/dedication/Dedications.java b/src/net/sourceforge/plantuml/dedication/Dedications.java
index ee78ca4e5..d44ecffa9 100644
--- a/src/net/sourceforge/plantuml/dedication/Dedications.java
+++ b/src/net/sourceforge/plantuml/dedication/Dedications.java
@@ -35,79 +35,60 @@
*/
package net.sourceforge.plantuml.dedication;
+import java.awt.image.BufferedImage;
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
import java.io.InputStream;
-import java.util.HashMap;
-import java.util.Map;
+import java.math.BigInteger;
+import java.util.ArrayList;
+import java.util.List;
-import net.sourceforge.plantuml.SignatureUtils;
+import net.sourceforge.plantuml.FileUtils;
public class Dedications {
- private static final Map normal = new HashMap();
- private static final Map crypted = new HashMap();
+ private static final List all = new ArrayList();
static {
- addNormal("Write your own dedication!", "dedication");
- addNormal("linux_china", "linux_china");
- addNormal("ARKBAN", "arkban");
- addNormal("Boundaries allow discipline to create true strength", "boundaries");
- addNormal("Thank you, Dr. Chet. I wouldn't be where I am without you", "dr_chet");
- addNormal("Ben and Jen 2020", "ben");
- addCrypted("0", "pOhci6rKgPXw32AeYXhOpSY0suoauHq5VUSwFqHLHsLYgSO6WaJ7BW5vtHBAoU6ePbcW7d8Flx99MWjPSKQTDm00");
- addCrypted("1", "LTxN3hdnhSJ515qcA7IQ841axt4GXfUd3n2wgNirYCdLnyX2360Gv1OEOnJ1-gwFzRW5B3HAqLBkR6Ge0WW_Z000");
- addCrypted("2", "lZqLduj4j1yRqSfAvkhbqVpqK8diklatiFeenDUXSdna9bKYQTzdS264YfUBScUVDYCp2Vcq04updoN98RwxE000");
+
+ try {
+ all.add(new DedicationSimple(load("dedication"), "Write your own dedication!"));
+ all.add(new DedicationSimple(load("linux_china"), "linux_china"));
+ all.add(new DedicationSimple(load("arkban"), "arkban"));
+ all.add(new DedicationSimple(load("boundaries"), "Boundaries allow discipline to create true strength"));
+ all.add(new DedicationSimple(load("dr_chet"), "Thank you, Dr. Chet. I wouldn't be where I am without you"));
+ all.add(new DedicationSimple(load("ben"), "Ben and Jen 2020"));
+ all.add(secret(5, "835ff5d643b58cd35a20db6480071d05751aa6a0e01da78662ceafd0161f3f5e", new BigInteger(
+ "1182423723677118831606503500858825217076578422970565964857326298418401529955036896808663335300684244453386039908536275400945824932191521017102701344437753036730900076162922741167523337650578479960119614237031234925702200473053235777")));
+ all.add(secret(3, "514816d583044efbd336882227deb822194ff63e3bdc3cf707a01f17770d5a6a", new BigInteger(
+ "538955952645999836068094511687012232127213955837942782605199622268460518023083462090291844640318324475656060087513198129259364840841077651829017347845508167869708224054456044836844382437974410757740941102771969965334031780041648873")));
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
}
- private static void addNormal(String sentence, String name) {
- normal.put(keepLetter(sentence), new Dedication(name));
+ private static DedicationCrypted secret(int tiny, String sig, BigInteger pq) throws IOException {
+ return new DedicationCrypted(load(sig), tiny, sig, pq);
}
- private static void addCrypted(String name, String contentKey) {
- crypted.put(contentKey, new Dedication(name));
+ private static byte[] load(String name) throws IOException {
+ final InputStream tmp = PSystemDedication.class.getResourceAsStream(name + ".png");
+ final ByteArrayOutputStream baos = new ByteArrayOutputStream();
+ FileUtils.copyInternal(tmp, baos, true);
+ return baos.toByteArray();
}
private Dedications() {
}
- public static Dedication get(String line) {
- final String keepLetter = keepLetter(line);
- final Dedication result = normal.get(keepLetter);
- if (result != null) {
- return result;
- }
- for (Map.Entry ent : crypted.entrySet()) {
- final Dedication dedication = ent.getValue();
- InputStream is = null;
- try {
- is = dedication.getInputStream(keepLetter);
- final String signature = SignatureUtils.getSignatureSha512(is);
- if (signature.equals(ent.getKey())) {
- return dedication;
- }
- } catch (Exception e) {
- e.printStackTrace();
- } finally {
- try {
- if (is != null)
- is.close();
- } catch (Exception e) {
- e.printStackTrace();
- }
+ public synchronized static BufferedImage get(String line) {
+ for (Dedication dedication : all) {
+ final BufferedImage image = dedication.getImage(line);
+ if (image != null) {
+ return image;
}
-
}
return null;
}
- public static String keepLetter(String s) {
- final StringBuilder sb = new StringBuilder();
- for (int i = 0; i < s.length(); i++) {
- final char c = s.charAt(i);
- if (Character.isLetterOrDigit(c)) {
- sb.append(c);
- }
- }
- return sb.toString();
- }
-
}
diff --git a/src/net/sourceforge/plantuml/dedication/Noise.java b/src/net/sourceforge/plantuml/dedication/Noise.java
index b6bae6cf6..9ec2dfc41 100644
--- a/src/net/sourceforge/plantuml/dedication/Noise.java
+++ b/src/net/sourceforge/plantuml/dedication/Noise.java
@@ -35,6 +35,80 @@
*/
package net.sourceforge.plantuml.dedication;
+import ext.plantuml.com.at.gadermaier.argon2.Argon2;
+import ext.plantuml.com.at.gadermaier.argon2.Argon2Factory;
+import ext.plantuml.com.at.gadermaier.argon2.model.Argon2Type;
+import net.sourceforge.plantuml.utils.MTRandom;
+
public class Noise {
+ private static Argon2 argon2(byte[] buffer, byte[] salt) {
+ final Argon2 argon = Argon2Factory.create() //
+ .setType(Argon2Type.Argon2id) //
+ .setMemory(8) //
+ .setSalt(salt.clone()) //
+ .setIterations(50) //
+ .setPassword(buffer.clone());
+ argon.hashNow();
+ return argon;
+ }
+
+ public static String computeArgon2String(byte[] buffer, byte[] salt) {
+ return argon2(buffer, salt).getOutputString();
+ }
+
+ public static byte[] computeArgon2bytes(byte[] buffer, byte[] salt) {
+ return argon2(buffer, salt).getOutput();
+ }
+
+ public static int shortHash(byte[] buffer, byte[] salt) {
+ final byte hash[] = argon2(buffer, salt).getOutput();
+ int result = 0;
+ for (byte b : hash) {
+ final int b1 = b & 0x0F;
+ final int b2 = (b & 0xF0) >> 4;
+ result ^= b1 ^ b2;
+ }
+ return result;
+ }
+
+ public static void shuffle(byte[] buffer, MTRandom rnd) {
+ for (int i = 0; i < buffer.length; i++) {
+ final int r1 = rnd.nextInt();
+ final int r2 = rnd.nextInt();
+ final int a = Math.abs(r1) % buffer.length;
+ final int b = Math.abs(r2) % buffer.length;
+ final byte tmp = buffer[a];
+ buffer[a] = buffer[b];
+ buffer[b] = tmp;
+ }
+ }
+
+ public static void xor(byte[] buffer, byte[] xor) {
+ for (int i = 0; i < buffer.length; i++) {
+ buffer[i] ^= xor[i % xor.length];
+ }
+ }
+
+ public static void xor(byte[] buffer, BlumBlumShub rnd) {
+ for (int i = 0; i < buffer.length; i++) {
+ final byte mask = (byte) (rnd.nextRnd(8) & 0xFF);
+ buffer[i] = (byte) (buffer[i] ^ mask);
+ }
+ }
+
+ public static byte[] reverse(byte[] buffer, int delta) {
+ delta = Math.abs(delta) % buffer.length;
+ final byte result[] = new byte[buffer.length];
+ for (int i = 0; i < buffer.length; i++)
+ result[i] = buffer[(buffer.length - 1 - i + delta) % buffer.length];
+ return result;
+ }
+
+
+
+
+
+
+
}
diff --git a/src/net/sourceforge/plantuml/dedication/PSystemDedication.java b/src/net/sourceforge/plantuml/dedication/PSystemDedication.java
index 82bf01fc3..17906d799 100644
--- a/src/net/sourceforge/plantuml/dedication/PSystemDedication.java
+++ b/src/net/sourceforge/plantuml/dedication/PSystemDedication.java
@@ -53,22 +53,20 @@ import net.sourceforge.plantuml.ugraphic.UImage;
public class PSystemDedication extends PlainDiagram {
- private final Dedication dedication;
- private final String keepLetter;
+ private final BufferedImage img;
- public PSystemDedication(Dedication dedication, String keepLetter) {
- this.dedication = dedication;
- this.keepLetter = keepLetter;
+ public PSystemDedication(BufferedImage img) {
+ this.img = img;
+ if (img == null) {
+ throw new IllegalArgumentException();
+ }
}
@Override
protected UDrawable getRootDrawable(FileFormatOption fileFormatOption) {
return new UDrawable() {
public void drawU(UGraphic ug) {
- final BufferedImage bufferedImage = dedication.getBufferedImage(keepLetter);
- if (bufferedImage != null) {
- ug.draw(new UImage(new PixelImage(bufferedImage, AffineTransformType.TYPE_BILINEAR)));
- }
+ ug.draw(new UImage(new PixelImage(img, AffineTransformType.TYPE_BILINEAR)));
}
};
}
diff --git a/src/net/sourceforge/plantuml/dedication/PSystemDedicationFactory.java b/src/net/sourceforge/plantuml/dedication/PSystemDedicationFactory.java
index 987a7c3e7..43e16f6e3 100644
--- a/src/net/sourceforge/plantuml/dedication/PSystemDedicationFactory.java
+++ b/src/net/sourceforge/plantuml/dedication/PSystemDedicationFactory.java
@@ -35,6 +35,8 @@
*/
package net.sourceforge.plantuml.dedication;
+import java.awt.image.BufferedImage;
+
import net.sourceforge.plantuml.AbstractPSystem;
import net.sourceforge.plantuml.command.PSystemSingleLineFactory;
@@ -42,9 +44,9 @@ public class PSystemDedicationFactory extends PSystemSingleLineFactory {
@Override
protected AbstractPSystem executeLine(String line) {
- final Dedication dedication = Dedications.get(line);
+ final BufferedImage dedication = Dedications.get(line);
if (dedication != null) {
- return new PSystemDedication(dedication, Dedications.keepLetter(line));
+ return new PSystemDedication(dedication);
}
return null;
}
diff --git a/src/net/sourceforge/plantuml/dedication/arkban.png b/src/net/sourceforge/plantuml/dedication/arkban.png
index 7ddc8131d..ab073d541 100644
Binary files a/src/net/sourceforge/plantuml/dedication/arkban.png and b/src/net/sourceforge/plantuml/dedication/arkban.png differ
diff --git a/src/net/sourceforge/plantuml/dedication/ben.png b/src/net/sourceforge/plantuml/dedication/ben.png
index e7756fb6e..ed0177f8f 100644
Binary files a/src/net/sourceforge/plantuml/dedication/ben.png and b/src/net/sourceforge/plantuml/dedication/ben.png differ
diff --git a/src/net/sourceforge/plantuml/dedication/boundaries.png b/src/net/sourceforge/plantuml/dedication/boundaries.png
index b989556e6..ae7fbd32d 100644
Binary files a/src/net/sourceforge/plantuml/dedication/boundaries.png and b/src/net/sourceforge/plantuml/dedication/boundaries.png differ
diff --git a/src/net/sourceforge/plantuml/dedication/dedication.png b/src/net/sourceforge/plantuml/dedication/dedication.png
index 0e6b8b280..fe727cebc 100644
Binary files a/src/net/sourceforge/plantuml/dedication/dedication.png and b/src/net/sourceforge/plantuml/dedication/dedication.png differ
diff --git a/src/net/sourceforge/plantuml/dedication/dr_chet.png b/src/net/sourceforge/plantuml/dedication/dr_chet.png
index 9d9c3930a..5c50730b7 100644
Binary files a/src/net/sourceforge/plantuml/dedication/dr_chet.png and b/src/net/sourceforge/plantuml/dedication/dr_chet.png differ
diff --git a/src/net/sourceforge/plantuml/dedication/linux_china.png b/src/net/sourceforge/plantuml/dedication/linux_china.png
index 3000b1598..e30928d7a 100644
Binary files a/src/net/sourceforge/plantuml/dedication/linux_china.png and b/src/net/sourceforge/plantuml/dedication/linux_china.png differ
diff --git a/src/net/sourceforge/plantuml/project/GanttDiagram.java b/src/net/sourceforge/plantuml/project/GanttDiagram.java
index ad9d011b9..cdd223f73 100644
--- a/src/net/sourceforge/plantuml/project/GanttDiagram.java
+++ b/src/net/sourceforge/plantuml/project/GanttDiagram.java
@@ -271,25 +271,30 @@ public class GanttDiagram extends TitledDiagram implements ToTaskDraw, WithSprit
private TimeHeader getTimeHeader() {
if (openClose.getCalendar() == null) {
- return new TimeHeaderSimple(min, max);
+ return new TimeHeaderSimple(min, max, getClosedStyle(), getIHtmlColorSet());
} else if (printScale == PrintScale.WEEKLY) {
return new TimeHeaderWeekly(getFactorScale(), openClose.getCalendar(), min, max, openClose, colorDays,
- colorDaysOfWeek, weekNumberStrategy);
+ colorDaysOfWeek, weekNumberStrategy, getClosedStyle(), getIHtmlColorSet());
} else if (printScale == PrintScale.MONTHLY) {
return new TimeHeaderMonthly(getFactorScale(), openClose.getCalendar(), min, max, openClose, colorDays,
- colorDaysOfWeek);
+ colorDaysOfWeek, getClosedStyle(), getIHtmlColorSet());
} else if (printScale == PrintScale.QUARTERLY) {
return new TimeHeaderQuarterly(getFactorScale(), openClose.getCalendar(), min, max, openClose, colorDays,
- colorDaysOfWeek);
+ colorDaysOfWeek, getClosedStyle(), getIHtmlColorSet());
} else if (printScale == PrintScale.YEARLY) {
return new TimeHeaderYearly(getFactorScale(), openClose.getCalendar(), min, max, openClose, colorDays,
- colorDaysOfWeek);
+ colorDaysOfWeek, getClosedStyle(), getIHtmlColorSet());
} else {
return new TimeHeaderDaily(openClose.getCalendar(), min, max, openClose, colorDays, colorDaysOfWeek,
- nameDays, printStart, printEnd);
+ nameDays, printStart, printEnd, getClosedStyle(), getIHtmlColorSet());
}
}
+ private Style getClosedStyle() {
+ return StyleSignature.of(SName.root, SName.element, SName.ganttDiagram, SName.closed)
+ .getMergedStyle(getCurrentStyleBuilder());
+ }
+
private double getTotalHeight(TimeHeader timeHeader) {
if (showFootbox) {
return totalHeightWithoutFooter + timeHeader.getTimeFooterHeight();
diff --git a/src/net/sourceforge/plantuml/project/draw/TimeHeader.java b/src/net/sourceforge/plantuml/project/draw/TimeHeader.java
index bb8c123f9..0fc1f7948 100644
--- a/src/net/sourceforge/plantuml/project/draw/TimeHeader.java
+++ b/src/net/sourceforge/plantuml/project/draw/TimeHeader.java
@@ -42,6 +42,8 @@ import net.sourceforge.plantuml.graphic.HorizontalAlignment;
import net.sourceforge.plantuml.graphic.TextBlock;
import net.sourceforge.plantuml.project.time.Day;
import net.sourceforge.plantuml.project.timescale.TimeScale;
+import net.sourceforge.plantuml.style.PName;
+import net.sourceforge.plantuml.style.Style;
import net.sourceforge.plantuml.ugraphic.UFont;
import net.sourceforge.plantuml.ugraphic.UGraphic;
import net.sourceforge.plantuml.ugraphic.ULine;
@@ -62,17 +64,30 @@ public abstract class TimeHeader {
return 28;
}
- protected final HColor veryLightGray = HColorSet.instance().getColorOrWhite("#E0E8E8");
- protected final HColor lightGray = HColorSet.instance().getColorOrWhite("#909898");
-
private final TimeScale timeScale;
+ private final Style style;
+ private final HColorSet colorSet;
+
protected final Day min;
protected final Day max;
- public TimeHeader(Day min, Day max, TimeScale timeScale) {
+ public TimeHeader(Day min, Day max, TimeScale timeScale, Style style, HColorSet colorSet) {
+ if (style == null) {
+ throw new IllegalArgumentException();
+ }
this.timeScale = timeScale;
this.min = min;
this.max = max;
+ this.style = style;
+ this.colorSet = colorSet;
+ }
+
+ protected final HColor closedBackgroundColor() {
+ return style.value(PName.BackGroundColor).asColor(colorSet);
+ }
+
+ protected final HColor closedFontColor() {
+ return style.value(PName.FontColor).asColor(colorSet);
}
public abstract double getTimeHeaderHeight();
diff --git a/src/net/sourceforge/plantuml/project/draw/TimeHeaderCalendar.java b/src/net/sourceforge/plantuml/project/draw/TimeHeaderCalendar.java
index 636063ceb..a68c9b9e8 100644
--- a/src/net/sourceforge/plantuml/project/draw/TimeHeaderCalendar.java
+++ b/src/net/sourceforge/plantuml/project/draw/TimeHeaderCalendar.java
@@ -41,8 +41,10 @@ import net.sourceforge.plantuml.project.LoadPlanable;
import net.sourceforge.plantuml.project.time.Day;
import net.sourceforge.plantuml.project.time.DayOfWeek;
import net.sourceforge.plantuml.project.timescale.TimeScale;
+import net.sourceforge.plantuml.style.Style;
import net.sourceforge.plantuml.ugraphic.UGraphic;
import net.sourceforge.plantuml.ugraphic.color.HColor;
+import net.sourceforge.plantuml.ugraphic.color.HColorSet;
public abstract class TimeHeaderCalendar extends TimeHeader {
@@ -51,8 +53,8 @@ public abstract class TimeHeaderCalendar extends TimeHeader {
protected final Map colorDaysOfWeek;
public TimeHeaderCalendar(Day calendar, Day min, Day max, LoadPlanable defaultPlan, Map colorDays,
- Map colorDaysOfWeek, TimeScale timeScale) {
- super(min, max, timeScale);
+ Map colorDaysOfWeek, TimeScale timeScale, Style style, HColorSet colorSet) {
+ super(min, max, timeScale, style, colorSet);
this.defaultPlan = defaultPlan;
this.colorDays = colorDays;
this.colorDaysOfWeek = colorDaysOfWeek;
@@ -89,7 +91,7 @@ public abstract class TimeHeaderCalendar extends TimeHeader {
back = backDoW;
}
if (back == null && defaultPlan.getLoadAt(wink) == 0) {
- back = veryLightGray;
+ back = closedBackgroundColor();
}
if (back == null) {
if (pending != null)
diff --git a/src/net/sourceforge/plantuml/project/draw/TimeHeaderDaily.java b/src/net/sourceforge/plantuml/project/draw/TimeHeaderDaily.java
index 0591796bd..afb53f974 100644
--- a/src/net/sourceforge/plantuml/project/draw/TimeHeaderDaily.java
+++ b/src/net/sourceforge/plantuml/project/draw/TimeHeaderDaily.java
@@ -43,10 +43,12 @@ import net.sourceforge.plantuml.project.time.Day;
import net.sourceforge.plantuml.project.time.DayOfWeek;
import net.sourceforge.plantuml.project.time.MonthYear;
import net.sourceforge.plantuml.project.timescale.TimeScaleDaily;
+import net.sourceforge.plantuml.style.Style;
import net.sourceforge.plantuml.ugraphic.UGraphic;
import net.sourceforge.plantuml.ugraphic.ULine;
import net.sourceforge.plantuml.ugraphic.UTranslate;
import net.sourceforge.plantuml.ugraphic.color.HColor;
+import net.sourceforge.plantuml.ugraphic.color.HColorSet;
import net.sourceforge.plantuml.ugraphic.color.HColorUtils;
public class TimeHeaderDaily extends TimeHeaderCalendar {
@@ -63,8 +65,10 @@ public class TimeHeaderDaily extends TimeHeaderCalendar {
private final Map nameDays;
public TimeHeaderDaily(Day calendar, Day min, Day max, LoadPlanable defaultPlan, Map colorDays,
- Map colorDaysOfWeek, Map nameDays, Day printStart, Day printEnd) {
- super(calendar, min, max, defaultPlan, colorDays, colorDaysOfWeek, new TimeScaleDaily(calendar, printStart));
+ Map colorDaysOfWeek, Map nameDays, Day printStart, Day printEnd,
+ Style style, HColorSet colorSet) {
+ super(calendar, min, max, defaultPlan, colorDays, colorDaysOfWeek, new TimeScaleDaily(calendar, printStart),
+ style, colorSet);
this.nameDays = nameDays;
}
@@ -111,7 +115,7 @@ public class TimeHeaderDaily extends TimeHeaderCalendar {
private HColor getTextBackColor(Day wink) {
if (defaultPlan.getLoadAt(wink) <= 0) {
- return lightGray;
+ return closedFontColor();
}
return HColorUtils.BLACK;
}
diff --git a/src/net/sourceforge/plantuml/project/draw/TimeHeaderMonthly.java b/src/net/sourceforge/plantuml/project/draw/TimeHeaderMonthly.java
index 67c5142c8..4fbc4f51e 100644
--- a/src/net/sourceforge/plantuml/project/draw/TimeHeaderMonthly.java
+++ b/src/net/sourceforge/plantuml/project/draw/TimeHeaderMonthly.java
@@ -43,10 +43,12 @@ import net.sourceforge.plantuml.project.time.Day;
import net.sourceforge.plantuml.project.time.DayOfWeek;
import net.sourceforge.plantuml.project.time.MonthYear;
import net.sourceforge.plantuml.project.timescale.TimeScaleCompressed;
+import net.sourceforge.plantuml.style.Style;
import net.sourceforge.plantuml.ugraphic.UGraphic;
import net.sourceforge.plantuml.ugraphic.ULine;
import net.sourceforge.plantuml.ugraphic.UTranslate;
import net.sourceforge.plantuml.ugraphic.color.HColor;
+import net.sourceforge.plantuml.ugraphic.color.HColorSet;
import net.sourceforge.plantuml.ugraphic.color.HColorUtils;
public class TimeHeaderMonthly extends TimeHeaderCalendar {
@@ -60,9 +62,9 @@ public class TimeHeaderMonthly extends TimeHeaderCalendar {
}
public TimeHeaderMonthly(double scale, Day calendar, Day min, Day max, LoadPlanable defaultPlan, Map colorDays,
- Map colorDaysOfWeek) {
+ Map colorDaysOfWeek, Style style, HColorSet colorSet) {
super(calendar, min, max, defaultPlan, colorDays, colorDaysOfWeek,
- new TimeScaleCompressed(calendar, scale));
+ new TimeScaleCompressed(calendar, scale), style, colorSet);
}
@Override
diff --git a/src/net/sourceforge/plantuml/project/draw/TimeHeaderQuarterly.java b/src/net/sourceforge/plantuml/project/draw/TimeHeaderQuarterly.java
index 45f7502d3..df2d4a68a 100644
--- a/src/net/sourceforge/plantuml/project/draw/TimeHeaderQuarterly.java
+++ b/src/net/sourceforge/plantuml/project/draw/TimeHeaderQuarterly.java
@@ -43,10 +43,12 @@ import net.sourceforge.plantuml.project.time.Day;
import net.sourceforge.plantuml.project.time.DayOfWeek;
import net.sourceforge.plantuml.project.time.MonthYear;
import net.sourceforge.plantuml.project.timescale.TimeScaleCompressed;
+import net.sourceforge.plantuml.style.Style;
import net.sourceforge.plantuml.ugraphic.UGraphic;
import net.sourceforge.plantuml.ugraphic.ULine;
import net.sourceforge.plantuml.ugraphic.UTranslate;
import net.sourceforge.plantuml.ugraphic.color.HColor;
+import net.sourceforge.plantuml.ugraphic.color.HColorSet;
import net.sourceforge.plantuml.ugraphic.color.HColorUtils;
public class TimeHeaderQuarterly extends TimeHeaderCalendar {
@@ -59,10 +61,10 @@ public class TimeHeaderQuarterly extends TimeHeaderCalendar {
return 16 + 13 - 1;
}
- public TimeHeaderQuarterly(double scale, Day calendar, Day min, Day max, LoadPlanable defaultPlan, Map colorDays,
- Map colorDaysOfWeek) {
- super(calendar, min, max, defaultPlan, colorDays, colorDaysOfWeek,
- new TimeScaleCompressed(calendar, scale));
+ public TimeHeaderQuarterly(double scale, Day calendar, Day min, Day max, LoadPlanable defaultPlan,
+ Map colorDays, Map colorDaysOfWeek, Style style, HColorSet colorSet) {
+ super(calendar, min, max, defaultPlan, colorDays, colorDaysOfWeek, new TimeScaleCompressed(calendar, scale),
+ style, colorSet);
}
@Override
@@ -126,9 +128,9 @@ public class TimeHeaderQuarterly extends TimeHeaderCalendar {
}
drawVbar(ug, getTimeScale().getEndingPosition(max), 0, 12);
}
-
+
private String quarter(Day day) {
- return "Q" + (( day.month().ordinal() + 3 ) / 3);
+ return "Q" + ((day.month().ordinal() + 3) / 3);
}
private void printYear(UGraphic ug, MonthYear monthYear, double start, double end) {
diff --git a/src/net/sourceforge/plantuml/project/draw/TimeHeaderSimple.java b/src/net/sourceforge/plantuml/project/draw/TimeHeaderSimple.java
index 2c120c967..5d4f1442c 100644
--- a/src/net/sourceforge/plantuml/project/draw/TimeHeaderSimple.java
+++ b/src/net/sourceforge/plantuml/project/draw/TimeHeaderSimple.java
@@ -42,9 +42,11 @@ import net.sourceforge.plantuml.graphic.TextBlock;
import net.sourceforge.plantuml.project.time.Day;
import net.sourceforge.plantuml.project.timescale.TimeScale;
import net.sourceforge.plantuml.project.timescale.TimeScaleWink;
+import net.sourceforge.plantuml.style.Style;
import net.sourceforge.plantuml.ugraphic.UGraphic;
import net.sourceforge.plantuml.ugraphic.ULine;
import net.sourceforge.plantuml.ugraphic.UTranslate;
+import net.sourceforge.plantuml.ugraphic.color.HColorSet;
import net.sourceforge.plantuml.ugraphic.color.HColorUtils;
public class TimeHeaderSimple extends TimeHeader {
@@ -66,8 +68,8 @@ public class TimeHeaderSimple extends TimeHeader {
return 0;
}
- public TimeHeaderSimple(Day min, Day max) {
- super(min, max, new TimeScaleWink());
+ public TimeHeaderSimple(Day min, Day max, Style style, HColorSet colorSet) {
+ super(min, max, new TimeScaleWink(), style, colorSet);
}
private void drawSmallVlinesDay(UGraphic ug, TimeScale timeScale, double totalHeightWithoutFooter) {
diff --git a/src/net/sourceforge/plantuml/project/draw/TimeHeaderWeekly.java b/src/net/sourceforge/plantuml/project/draw/TimeHeaderWeekly.java
index 091f8c157..5a3909568 100644
--- a/src/net/sourceforge/plantuml/project/draw/TimeHeaderWeekly.java
+++ b/src/net/sourceforge/plantuml/project/draw/TimeHeaderWeekly.java
@@ -44,10 +44,12 @@ import net.sourceforge.plantuml.project.time.DayOfWeek;
import net.sourceforge.plantuml.project.time.MonthYear;
import net.sourceforge.plantuml.project.time.WeekNumberStrategy;
import net.sourceforge.plantuml.project.timescale.TimeScaleCompressed;
+import net.sourceforge.plantuml.style.Style;
import net.sourceforge.plantuml.ugraphic.UGraphic;
import net.sourceforge.plantuml.ugraphic.ULine;
import net.sourceforge.plantuml.ugraphic.UTranslate;
import net.sourceforge.plantuml.ugraphic.color.HColor;
+import net.sourceforge.plantuml.ugraphic.color.HColorSet;
import net.sourceforge.plantuml.ugraphic.color.HColorUtils;
public class TimeHeaderWeekly extends TimeHeaderCalendar {
@@ -63,8 +65,10 @@ public class TimeHeaderWeekly extends TimeHeaderCalendar {
}
public TimeHeaderWeekly(double scale, Day calendar, Day min, Day max, LoadPlanable defaultPlan,
- Map colorDays, Map colorDaysOfWeek, WeekNumberStrategy weekNumberStrategy) {
- super(calendar, min, max, defaultPlan, colorDays, colorDaysOfWeek, new TimeScaleCompressed(calendar, scale));
+ Map colorDays, Map colorDaysOfWeek, WeekNumberStrategy weekNumberStrategy,
+ Style style, HColorSet colorSet) {
+ super(calendar, min, max, defaultPlan, colorDays, colorDaysOfWeek, new TimeScaleCompressed(calendar, scale),
+ style, colorSet);
this.weekNumberStrategy = weekNumberStrategy;
}
diff --git a/src/net/sourceforge/plantuml/project/draw/TimeHeaderYearly.java b/src/net/sourceforge/plantuml/project/draw/TimeHeaderYearly.java
index 1b9e2f44e..c2583dcb2 100644
--- a/src/net/sourceforge/plantuml/project/draw/TimeHeaderYearly.java
+++ b/src/net/sourceforge/plantuml/project/draw/TimeHeaderYearly.java
@@ -43,10 +43,12 @@ import net.sourceforge.plantuml.project.time.Day;
import net.sourceforge.plantuml.project.time.DayOfWeek;
import net.sourceforge.plantuml.project.time.MonthYear;
import net.sourceforge.plantuml.project.timescale.TimeScaleCompressed;
+import net.sourceforge.plantuml.style.Style;
import net.sourceforge.plantuml.ugraphic.UGraphic;
import net.sourceforge.plantuml.ugraphic.ULine;
import net.sourceforge.plantuml.ugraphic.UTranslate;
import net.sourceforge.plantuml.ugraphic.color.HColor;
+import net.sourceforge.plantuml.ugraphic.color.HColorSet;
import net.sourceforge.plantuml.ugraphic.color.HColorUtils;
public class TimeHeaderYearly extends TimeHeaderCalendar {
@@ -60,8 +62,9 @@ public class TimeHeaderYearly extends TimeHeaderCalendar {
}
public TimeHeaderYearly(double scale, Day calendar, Day min, Day max, LoadPlanable defaultPlan,
- Map colorDays, Map colorDaysOfWeek) {
- super(calendar, min, max, defaultPlan, colorDays, colorDaysOfWeek, new TimeScaleCompressed(calendar, scale));
+ Map colorDays, Map colorDaysOfWeek, Style style, HColorSet colorSet) {
+ super(calendar, min, max, defaultPlan, colorDays, colorDaysOfWeek, new TimeScaleCompressed(calendar, scale),
+ style, colorSet);
}
@Override
diff --git a/src/net/sourceforge/plantuml/style/SName.java b/src/net/sourceforge/plantuml/style/SName.java
index 4e0284e7f..5ea3a1d9b 100644
--- a/src/net/sourceforge/plantuml/style/SName.java
+++ b/src/net/sourceforge/plantuml/style/SName.java
@@ -54,6 +54,7 @@ public enum SName {
class_, //
clickable, //
cloud, //
+ closed, //
collection, //
collections, //
component, //
diff --git a/src/net/sourceforge/plantuml/svek/image/EntityImageLollipopInterfaceEye1.java b/src/net/sourceforge/plantuml/svek/image/EntityImageLollipopInterfaceEye1.java
index 1c625eae4..875bad9c3 100644
--- a/src/net/sourceforge/plantuml/svek/image/EntityImageLollipopInterfaceEye1.java
+++ b/src/net/sourceforge/plantuml/svek/image/EntityImageLollipopInterfaceEye1.java
@@ -53,8 +53,8 @@ import net.sourceforge.plantuml.graphic.StringBounder;
import net.sourceforge.plantuml.graphic.TextBlock;
import net.sourceforge.plantuml.svek.AbstractEntityImage;
import net.sourceforge.plantuml.svek.Bibliotekon;
-import net.sourceforge.plantuml.svek.SvekLine;
import net.sourceforge.plantuml.svek.ShapeType;
+import net.sourceforge.plantuml.svek.SvekLine;
import net.sourceforge.plantuml.ugraphic.UEllipse;
import net.sourceforge.plantuml.ugraphic.UGraphic;
import net.sourceforge.plantuml.ugraphic.UStroke;
diff --git a/src/net/sourceforge/plantuml/svek/image/EntityImageNote.java b/src/net/sourceforge/plantuml/svek/image/EntityImageNote.java
index 79ad6eddc..c910e7728 100644
--- a/src/net/sourceforge/plantuml/svek/image/EntityImageNote.java
+++ b/src/net/sourceforge/plantuml/svek/image/EntityImageNote.java
@@ -71,8 +71,8 @@ import net.sourceforge.plantuml.style.SName;
import net.sourceforge.plantuml.style.Style;
import net.sourceforge.plantuml.style.StyleSignature;
import net.sourceforge.plantuml.svek.AbstractEntityImage;
-import net.sourceforge.plantuml.svek.SvekLine;
import net.sourceforge.plantuml.svek.ShapeType;
+import net.sourceforge.plantuml.svek.SvekLine;
import net.sourceforge.plantuml.svek.SvekNode;
import net.sourceforge.plantuml.ugraphic.UGraphic;
import net.sourceforge.plantuml.ugraphic.UGraphicStencil;
diff --git a/src/net/sourceforge/plantuml/svek/image/EntityImageState.java b/src/net/sourceforge/plantuml/svek/image/EntityImageState.java
index 8672656fe..51ebd158f 100644
--- a/src/net/sourceforge/plantuml/svek/image/EntityImageState.java
+++ b/src/net/sourceforge/plantuml/svek/image/EntityImageState.java
@@ -37,13 +37,9 @@ package net.sourceforge.plantuml.svek.image;
import java.awt.geom.Dimension2D;
-import net.sourceforge.plantuml.ColorParam;
import net.sourceforge.plantuml.Dimension2DDouble;
import net.sourceforge.plantuml.FontParam;
import net.sourceforge.plantuml.ISkinParam;
-import net.sourceforge.plantuml.LineConfigurable;
-import net.sourceforge.plantuml.SkinParamUtils;
-import net.sourceforge.plantuml.Url;
import net.sourceforge.plantuml.creole.CreoleMode;
import net.sourceforge.plantuml.cucadiagram.Display;
import net.sourceforge.plantuml.cucadiagram.IEntity;
@@ -52,24 +48,16 @@ import net.sourceforge.plantuml.graphic.FontConfiguration;
import net.sourceforge.plantuml.graphic.HorizontalAlignment;
import net.sourceforge.plantuml.graphic.StringBounder;
import net.sourceforge.plantuml.graphic.TextBlock;
-import net.sourceforge.plantuml.graphic.color.ColorType;
-import net.sourceforge.plantuml.svek.AbstractEntityImage;
-import net.sourceforge.plantuml.svek.ShapeType;
-import net.sourceforge.plantuml.ugraphic.Shadowable;
import net.sourceforge.plantuml.ugraphic.UEllipse;
import net.sourceforge.plantuml.ugraphic.UGraphic;
import net.sourceforge.plantuml.ugraphic.UGroupType;
import net.sourceforge.plantuml.ugraphic.ULine;
-import net.sourceforge.plantuml.ugraphic.URectangle;
import net.sourceforge.plantuml.ugraphic.UStroke;
import net.sourceforge.plantuml.ugraphic.UTranslate;
-import net.sourceforge.plantuml.ugraphic.color.HColor;
-public class EntityImageState extends AbstractEntityImage {
+public class EntityImageState extends EntityImageStateCommon {
- final private TextBlock desc;
final private TextBlock fields;
- final private Url url;
final private static int MIN_WIDTH = 50;
final private static int MIN_HEIGHT = 50;
@@ -81,25 +69,13 @@ public class EntityImageState extends AbstractEntityImage {
final static private double smallMarginX = 7;
final static private double smallMarginY = 4;
- final private LineConfigurable lineConfig;
-
public EntityImageState(IEntity entity, ISkinParam skinParam) {
super(entity, skinParam);
- this.lineConfig = entity;
+
final Stereotype stereotype = entity.getStereotype();
+
this.withSymbol = stereotype != null && stereotype.isWithOOSymbol();
-
- this.desc = entity.getDisplay().create8(new FontConfiguration(getSkinParam(), FontParam.STATE, stereotype),
- HorizontalAlignment.CENTER, skinParam, CreoleMode.FULL, skinParam.wrapWidth());
-
-// Display list = Display.empty();
-// for (Member att : entity.getBodier().getFieldsToDisplay()) {
-// list = list.addAll(Display.getWithNewlines(att.getDisplay(true)));
-// }
final Display list = Display.create(entity.getBodier().getRawBody());
-
- this.url = entity.getUrl99();
-
this.fields = list.create8(new FontConfiguration(getSkinParam(), FontParam.STATE_ATTRIBUTE, stereotype),
HorizontalAlignment.LEFT, skinParam, CreoleMode.FULL, skinParam.wrapWidth());
@@ -125,28 +101,11 @@ public class EntityImageState extends AbstractEntityImage {
final Dimension2D dimTotal = calculateDimension(stringBounder);
final Dimension2D dimDesc = desc.calculateDimension(stringBounder);
- final double widthTotal = dimTotal.getWidth();
- final double heightTotal = dimTotal.getHeight();
- final Shadowable rect = new URectangle(widthTotal, heightTotal).rounded(CORNER);
- if (getSkinParam().shadowing(getEntity().getStereotype())) {
- rect.setDeltaShadow(4);
- }
-
- HColor classBorder = lineConfig.getColors(getSkinParam()).getColor(ColorType.LINE);
- if (classBorder == null) {
- classBorder = SkinParamUtils.getColor(getSkinParam(), getStereo(), ColorParam.stateBorder);
- }
- ug = ug.apply(getStroke()).apply(classBorder);
- HColor backcolor = getEntity().getColors(getSkinParam()).getColor(ColorType.BACK);
- if (backcolor == null) {
- backcolor = SkinParamUtils.getColor(getSkinParam(), getStereo(), ColorParam.stateBackground);
- }
- ug = ug.apply(backcolor.bg());
-
- ug.draw(rect);
+ ug = applyColor(ug);
+ ug.draw(getShape(dimTotal));
final double yLine = MARGIN + dimDesc.getHeight() + MARGIN_LINE;
- ug.apply(UTranslate.dy(yLine)).draw(ULine.hline(widthTotal));
+ ug.apply(UTranslate.dy(yLine)).draw(ULine.hline(dimTotal.getWidth()));
ug = ug.apply(new UStroke());
@@ -156,7 +115,7 @@ public class EntityImageState extends AbstractEntityImage {
drawSymbol(ug, xSymbol, ySymbol);
}
- final double xDesc = (widthTotal - dimDesc.getWidth()) / 2;
+ final double xDesc = (dimTotal.getWidth() - dimDesc.getWidth()) / 2;
final double yDesc = MARGIN;
desc.drawU(ug.apply(new UTranslate(xDesc, yDesc)));
@@ -170,14 +129,6 @@ public class EntityImageState extends AbstractEntityImage {
ug.closeGroup();
}
- private UStroke getStroke() {
- UStroke stroke = lineConfig.getColors(getSkinParam()).getSpecificLineStroke();
- if (stroke == null) {
- stroke = new UStroke(1.5);
- }
- return stroke;
- }
-
public static void drawSymbol(UGraphic ug, double xSymbol, double ySymbol) {
xSymbol -= 4 * smallRadius + smallLine + smallMarginX;
ySymbol -= 2 * smallRadius + smallMarginY;
@@ -187,8 +138,4 @@ public class EntityImageState extends AbstractEntityImage {
ug.apply(new UTranslate(xSymbol + 2 * smallRadius, ySymbol + smallLine)).draw(ULine.hline(smallLine));
}
- public ShapeType getShapeType() {
- return ShapeType.ROUND_RECTANGLE;
- }
-
}
diff --git a/src/net/sourceforge/plantuml/svek/image/EntityImageState2.java b/src/net/sourceforge/plantuml/svek/image/EntityImageState2.java
index adf31d6c4..203a16f2f 100644
--- a/src/net/sourceforge/plantuml/svek/image/EntityImageState2.java
+++ b/src/net/sourceforge/plantuml/svek/image/EntityImageState2.java
@@ -63,22 +63,15 @@ import net.sourceforge.plantuml.ugraphic.color.HColor;
public class EntityImageState2 extends AbstractEntityImage {
final private Url url;
-
- final private LineConfigurable lineConfig;
+ // final private LineConfigurable lineConfig;
private final TextBlock asSmall;
public EntityImageState2(ILeaf entity, ISkinParam skinParam) {
super(entity, skinParam);
- this.lineConfig = entity;
+ // this.lineConfig = entity;
final Stereotype stereotype = entity.getStereotype();
-// Display list = Display.empty();
-// for (Member att : entity.getBodier().getFieldsToDisplay()) {
-// list = list.addAll(Display.getWithNewlines(att.getDisplay(true)));
-// }
- // final Display list = Display.create(entity.getBodier().getRawBody());
-
final USymbol symbol = USymbol.FRAME;
HColor backcolor = getEntity().getColors(getSkinParam()).getColor(ColorType.BACK);
diff --git a/src/net/sourceforge/plantuml/svek/image/EntityImageStateCommon.java b/src/net/sourceforge/plantuml/svek/image/EntityImageStateCommon.java
new file mode 100644
index 000000000..1b5e3c048
--- /dev/null
+++ b/src/net/sourceforge/plantuml/svek/image/EntityImageStateCommon.java
@@ -0,0 +1,115 @@
+/* ========================================================================
+ * PlantUML : a free UML diagram generator
+ * ========================================================================
+ *
+ * (C) Copyright 2009-2020, Arnaud Roques
+ *
+ * Project Info: http://plantuml.com
+ *
+ * If you like this project or if you find it useful, you can support us at:
+ *
+ * http://plantuml.com/patreon (only 1$ per month!)
+ * http://plantuml.com/paypal
+ *
+ * This file is part of PlantUML.
+ *
+ * PlantUML is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * PlantUML distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
+ * License for more details.
+ *
+ * You should have received a copy of the GNU General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
+ * USA.
+ *
+ *
+ * Original Author: Arnaud Roques
+ *
+ *
+ */
+package net.sourceforge.plantuml.svek.image;
+
+import java.awt.geom.Dimension2D;
+
+import net.sourceforge.plantuml.ColorParam;
+import net.sourceforge.plantuml.FontParam;
+import net.sourceforge.plantuml.ISkinParam;
+import net.sourceforge.plantuml.LineConfigurable;
+import net.sourceforge.plantuml.SkinParamUtils;
+import net.sourceforge.plantuml.Url;
+import net.sourceforge.plantuml.creole.CreoleMode;
+import net.sourceforge.plantuml.cucadiagram.IEntity;
+import net.sourceforge.plantuml.cucadiagram.Stereotype;
+import net.sourceforge.plantuml.graphic.FontConfiguration;
+import net.sourceforge.plantuml.graphic.HorizontalAlignment;
+import net.sourceforge.plantuml.graphic.TextBlock;
+import net.sourceforge.plantuml.graphic.color.ColorType;
+import net.sourceforge.plantuml.svek.AbstractEntityImage;
+import net.sourceforge.plantuml.svek.ShapeType;
+import net.sourceforge.plantuml.ugraphic.UGraphic;
+import net.sourceforge.plantuml.ugraphic.URectangle;
+import net.sourceforge.plantuml.ugraphic.UStroke;
+import net.sourceforge.plantuml.ugraphic.color.HColor;
+
+public abstract class EntityImageStateCommon extends AbstractEntityImage {
+
+ final protected TextBlock desc;
+ final protected Url url;
+
+ final protected LineConfigurable lineConfig;
+
+ public EntityImageStateCommon(IEntity entity, ISkinParam skinParam) {
+ super(entity, skinParam);
+
+ this.lineConfig = entity;
+ final Stereotype stereotype = entity.getStereotype();
+
+ this.desc = entity.getDisplay().create8(new FontConfiguration(getSkinParam(), FontParam.STATE, stereotype),
+ HorizontalAlignment.CENTER, skinParam, CreoleMode.FULL, skinParam.wrapWidth());
+ this.url = entity.getUrl99();
+
+ }
+
+ final protected UStroke getStroke() {
+ UStroke stroke = lineConfig.getColors(getSkinParam()).getSpecificLineStroke();
+ if (stroke == null) {
+ stroke = new UStroke(1.5);
+ }
+ return stroke;
+ }
+
+ final public ShapeType getShapeType() {
+ return ShapeType.ROUND_RECTANGLE;
+ }
+
+ final protected URectangle getShape(final Dimension2D dimTotal) {
+ final URectangle rect = new URectangle(dimTotal).rounded(CORNER);
+ if (getSkinParam().shadowing(getEntity().getStereotype())) {
+ rect.setDeltaShadow(4);
+ }
+ return rect;
+ }
+
+ final protected UGraphic applyColor(UGraphic ug) {
+
+ HColor classBorder = lineConfig.getColors(getSkinParam()).getColor(ColorType.LINE);
+ if (classBorder == null) {
+ classBorder = SkinParamUtils.getColor(getSkinParam(), getStereo(), ColorParam.stateBorder);
+ }
+ ug = ug.apply(getStroke()).apply(classBorder);
+ HColor backcolor = getEntity().getColors(getSkinParam()).getColor(ColorType.BACK);
+ if (backcolor == null) {
+ backcolor = SkinParamUtils.getColor(getSkinParam(), getStereo(), ColorParam.stateBackground);
+ }
+ ug = ug.apply(backcolor.bg());
+
+ return ug;
+ }
+
+}
diff --git a/src/net/sourceforge/plantuml/svek/image/EntityImageStateEmptyDescription.java b/src/net/sourceforge/plantuml/svek/image/EntityImageStateEmptyDescription.java
index 23e1e758d..aa025fa49 100644
--- a/src/net/sourceforge/plantuml/svek/image/EntityImageStateEmptyDescription.java
+++ b/src/net/sourceforge/plantuml/svek/image/EntityImageStateEmptyDescription.java
@@ -37,51 +37,20 @@ package net.sourceforge.plantuml.svek.image;
import java.awt.geom.Dimension2D;
-import net.sourceforge.plantuml.ColorParam;
import net.sourceforge.plantuml.Dimension2DDouble;
-import net.sourceforge.plantuml.FontParam;
import net.sourceforge.plantuml.ISkinParam;
-import net.sourceforge.plantuml.SkinParamUtils;
-import net.sourceforge.plantuml.Url;
-import net.sourceforge.plantuml.creole.CreoleMode;
import net.sourceforge.plantuml.cucadiagram.IEntity;
-import net.sourceforge.plantuml.cucadiagram.Stereotype;
-import net.sourceforge.plantuml.graphic.FontConfiguration;
-import net.sourceforge.plantuml.graphic.HorizontalAlignment;
import net.sourceforge.plantuml.graphic.StringBounder;
-import net.sourceforge.plantuml.graphic.TextBlock;
-import net.sourceforge.plantuml.graphic.color.ColorType;
-import net.sourceforge.plantuml.svek.AbstractEntityImage;
-import net.sourceforge.plantuml.svek.ShapeType;
-import net.sourceforge.plantuml.ugraphic.Shadowable;
import net.sourceforge.plantuml.ugraphic.UGraphic;
-import net.sourceforge.plantuml.ugraphic.URectangle;
-import net.sourceforge.plantuml.ugraphic.UStroke;
import net.sourceforge.plantuml.ugraphic.UTranslate;
-import net.sourceforge.plantuml.ugraphic.color.HColor;
-public class EntityImageStateEmptyDescription extends AbstractEntityImage {
-
- final private TextBlock desc;
- final private Url url;
+public class EntityImageStateEmptyDescription extends EntityImageStateCommon {
final private static int MIN_WIDTH = 50;
final private static int MIN_HEIGHT = 40;
public EntityImageStateEmptyDescription(IEntity entity, ISkinParam skinParam) {
super(entity, skinParam);
- final Stereotype stereotype = entity.getStereotype();
-
- this.desc = entity.getDisplay().create8(new FontConfiguration(getSkinParam(), FontParam.STATE, stereotype),
- HorizontalAlignment.CENTER, skinParam, CreoleMode.FULL, skinParam.wrapWidth());
-
-// Display list = Display.empty();
-// for (Member att : entity.getBodier().getFieldsToDisplay()) {
-// list = list.addAll(Display.getWithNewlines(att.getDisplay(true)));
-// }
-// final Display list = Display.create(entity.getBodier().getRawBody());
-
- this.url = entity.getUrl99();
}
@@ -99,23 +68,11 @@ public class EntityImageStateEmptyDescription extends AbstractEntityImage {
final Dimension2D dimTotal = calculateDimension(stringBounder);
final Dimension2D dimDesc = desc.calculateDimension(stringBounder);
- final double widthTotal = dimTotal.getWidth();
- final double heightTotal = dimTotal.getHeight();
- final Shadowable rect = new URectangle(widthTotal, heightTotal).rounded(CORNER);
- if (getSkinParam().shadowing(getEntity().getStereotype())) {
- rect.setDeltaShadow(4);
- }
+ ug = applyColor(ug);
+ ug.draw(getShape(dimTotal));
- ug = ug.apply(new UStroke(1.5))
- .apply(SkinParamUtils.getColor(getSkinParam(), getStereo(), ColorParam.stateBorder));
- HColor backcolor = getEntity().getColors(getSkinParam()).getColor(ColorType.BACK);
- if (backcolor == null) {
- backcolor = SkinParamUtils.getColor(getSkinParam(), getStereo(), ColorParam.stateBackground);
- }
- ug = ug.apply(backcolor.bg());
- ug.draw(rect);
- final double xDesc = (widthTotal - dimDesc.getWidth()) / 2;
- final double yDesc = (heightTotal - dimDesc.getHeight()) / 2;
+ final double xDesc = (dimTotal.getWidth() - dimDesc.getWidth()) / 2;
+ final double yDesc = (dimTotal.getHeight() - dimDesc.getHeight()) / 2;
desc.drawU(ug.apply(new UTranslate(xDesc, yDesc)));
if (url != null) {
@@ -123,8 +80,4 @@ public class EntityImageStateEmptyDescription extends AbstractEntityImage {
}
}
- public ShapeType getShapeType() {
- return ShapeType.ROUND_RECTANGLE;
- }
-
}
diff --git a/src/net/sourceforge/plantuml/version/PSystemVersion.java b/src/net/sourceforge/plantuml/version/PSystemVersion.java
index 8f57cca90..fdf0066e3 100644
--- a/src/net/sourceforge/plantuml/version/PSystemVersion.java
+++ b/src/net/sourceforge/plantuml/version/PSystemVersion.java
@@ -34,6 +34,8 @@
*/
package net.sourceforge.plantuml.version;
+import static net.sourceforge.plantuml.graphic.GraphicPosition.BACKGROUND_CORNER_BOTTOM_RIGHT;
+
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.io.InputStream;
@@ -47,7 +49,7 @@ import net.sourceforge.plantuml.PlainStringsDiagram;
import net.sourceforge.plantuml.Run;
import net.sourceforge.plantuml.core.DiagramDescription;
import net.sourceforge.plantuml.cucadiagram.dot.GraphvizUtils;
-import net.sourceforge.plantuml.dedication.Dedication;
+import net.sourceforge.plantuml.dedication.PSystemDedication;
import net.sourceforge.plantuml.preproc.ImportedFiles;
import net.sourceforge.plantuml.preproc.Stdlib;
import net.sourceforge.plantuml.preproc2.PreprocessorUtils;
@@ -57,8 +59,6 @@ import net.sourceforge.plantuml.security.SecurityProfile;
import net.sourceforge.plantuml.security.SecurityUtils;
import net.sourceforge.plantuml.svek.GraphvizCrash;
-import static net.sourceforge.plantuml.graphic.GraphicPosition.BACKGROUND_CORNER_BOTTOM_RIGHT;
-
public class PSystemVersion extends PlainStringsDiagram {
PSystemVersion(boolean withImage, List args) {
@@ -126,7 +126,7 @@ public class PSystemVersion extends PlainStringsDiagram {
private static BufferedImage getImageWebp(final String name) {
try {
final InputStream is = PSystemVersion.class.getResourceAsStream(name);
- final BufferedImage image = Dedication.getBufferedImage(is);
+ final BufferedImage image = PSystemDedication.getBufferedImage(is);
is.close();
return image;
} catch (IOException e) {
diff --git a/src/net/sourceforge/plantuml/version/Version.java b/src/net/sourceforge/plantuml/version/Version.java
index 237c51db7..0f2f87632 100644
--- a/src/net/sourceforge/plantuml/version/Version.java
+++ b/src/net/sourceforge/plantuml/version/Version.java
@@ -44,7 +44,7 @@ public class Version {
private static final int MAJOR_SEPARATOR = 1000000;
public static int version() {
- return 1202104;
+ return 1202105;
}
public static int versionPatched() {
@@ -80,7 +80,7 @@ public class Version {
}
public static int beta() {
- final int beta = 5;
+ final int beta = 0;
return beta;
}
@@ -93,7 +93,7 @@ public class Version {
}
public static long compileTime() {
- return 1617526179012L;
+ return 1619349628741L;
}
public static String compileTimeString() {
diff --git a/svg/default.css b/svg/default.css
deleted file mode 100644
index aecd589ec..000000000
--- a/svg/default.css
+++ /dev/null
@@ -1,3 +0,0 @@
-.elem {cursor: pointer;}
-.elem, .link {opacity: 0.3;}
-.elem.selected, .link.selected {opacity: 1;}
\ No newline at end of file
diff --git a/svg/default.js b/svg/default.js
deleted file mode 100644
index 27da2a695..000000000
--- a/svg/default.js
+++ /dev/null
@@ -1,110 +0,0 @@
-function addItemToMapOfLists(mapOfLists, name, item) {
- // mapOfLists = {
- // 'key1': [item1, item2, ...],
- // 'key2': [item3, item4, ...],
- // }
- if (mapOfLists[name].length > 0) {
- if (!mapOfLists[name].includes(item)) {
- mapOfLists[name].push(item);
- }
- } else {
- mapOfLists[name] = [item];
- }
-}
-
-function main() {
- let elems = Array.from(document.getElementsByClassName('elem'));
- let links = Array.from(document.getElementsByClassName('link'));
-
- let elemsMap = {};
- let linkedElems = {};
- let linkedLinks = {};
-
- elems.forEach(elem => {
- let name = elem.classList[1];
- elemsMap[name] = elem;
- linkedElems[name] = [];
- linkedLinks[name] = [];
- });
-
- links.forEach(link => {
- let name1 = link.classList[1];
- let name2 = link.classList[2];
-
- if (elemsMap[name1]) {
- if (elemsMap[name2]) {
- let elem1 = elemsMap[name1];
- let elem2 = elemsMap[name2];
-
- addItemToMapOfLists(linkedElems, name1, elem2);
- addItemToMapOfLists(linkedElems, name2, elem1);
-
- addItemToMapOfLists(linkedLinks, name1, link);
- addItemToMapOfLists(linkedLinks, name2, link);
- }
- }
- });
-
- let selectedElems = [];
- let selectedLinks = [];
- let selectedElemName = null;
-
- function clearSelected() {
- selectedElems.forEach(item => {
- item.classList.remove('selected');
- });
- selectedElems = [];
-
- selectedLinks.forEach(item => {
- item.classList.remove('selected');
- });
- selectedLinks = [];
- }
-
- function selectAll() {
- selectedElemName = null;
-
- selectedElems = Array.from(elems);
- selectedElems.forEach(item => {
- item.classList.add('selected');
- });
-
- selectedLinks = Array.from(links);
- selectedLinks.forEach(item => {
- item.classList.add('selected');
- });
- }
-
- function selectElem(elemName) {
- if (elemName === selectedElemName) {
- selectAll();
-
- } else {
- clearSelected();
- selectedElemName = elemName;
-
- elemsMap[elemName].classList.add('selected');
- selectedElems.push(elemsMap[elemName]);
-
- linkedElems[elemName].forEach(linkedElem => {
- selectedElems.push(linkedElem);
- linkedElem.classList.add('selected');
- });
-
- linkedLinks[elemName].forEach(linkedLink => {
- selectedLinks.push(linkedLink);
- linkedLink.classList.add('selected');
- });
- }
- }
-
- Object.keys(elemsMap).forEach(name => {
- elemsMap[name].onclick = () => { selectElem(name); };
- });
-
- selectAll();
-}
-
-document.addEventListener('DOMContentLoaded', (event) => {
- main();
-});