diff options
Diffstat (limited to 'src/cz/crcs/ectester/common/ec')
| -rw-r--r-- | src/cz/crcs/ectester/common/ec/EC_Category.java | 142 | ||||
| -rw-r--r-- | src/cz/crcs/ectester/common/ec/EC_Curve.java | 132 | ||||
| -rw-r--r-- | src/cz/crcs/ectester/common/ec/EC_Data.java | 217 | ||||
| -rw-r--r-- | src/cz/crcs/ectester/common/ec/EC_KAResult.java | 65 | ||||
| -rw-r--r-- | src/cz/crcs/ectester/common/ec/EC_Key.java | 83 | ||||
| -rw-r--r-- | src/cz/crcs/ectester/common/ec/EC_Keypair.java | 41 | ||||
| -rw-r--r-- | src/cz/crcs/ectester/common/ec/EC_Params.java | 194 |
7 files changed, 874 insertions, 0 deletions
diff --git a/src/cz/crcs/ectester/common/ec/EC_Category.java b/src/cz/crcs/ectester/common/ec/EC_Category.java new file mode 100644 index 0000000..32a788d --- /dev/null +++ b/src/cz/crcs/ectester/common/ec/EC_Category.java @@ -0,0 +1,142 @@ +package cz.crcs.ectester.common.ec; + +import java.util.Collections; +import java.util.Map; +import java.util.Objects; +import java.util.TreeMap; + +/** + * A category of EC_Data objects, has a name, description and represents a directory in + * the cz.crcs.ectester.data package. + * @author Jan Jancar johny@neuromancer.sk + */ +public class EC_Category { + + private String name; + private String directory; + private String desc; + + private Map<String, EC_Data> objects; + + + public EC_Category(String name, String directory) { + this.name = name; + this.directory = directory; + } + + public EC_Category(String name, String directory, String desc) { + this(name, directory); + this.desc = desc; + } + + public EC_Category(String name, String directory, String desc, Map<String, EC_Data> objects) { + this(name, directory, desc); + this.objects = objects; + } + + public String getName() { + return name; + } + + public String getDirectory() { + return directory; + } + + public String getDesc() { + return desc; + } + + public Map<String, EC_Data> getObjects() { + return Collections.unmodifiableMap(objects); + } + + public <T extends EC_Data> Map<String, T> getObjects(Class<T> cls) { + Map<String, T> objs = new TreeMap<>(); + for (Map.Entry<String, EC_Data> entry : objects.entrySet()) { + if (cls.isInstance(entry.getValue())) { + objs.put(entry.getKey(), cls.cast(entry.getValue())); + } + } + return Collections.unmodifiableMap(objs); + } + + public <T extends EC_Data> T getObject(Class<T> cls, String id) { + EC_Data obj = objects.get(id); + if (cls.isInstance(obj)) { + return cls.cast(obj); + } else { + return null; + } + } + + @Override + public String toString() { + StringBuilder out = new StringBuilder(); + out.append("\t- ").append(name).append((desc == null || desc.equals("")) ? "" : ": " + desc); + out.append(System.lineSeparator()); + + Map<String, EC_Curve> curves = getObjects(EC_Curve.class); + int size = curves.size(); + if (size > 0) { + out.append("\t\tCurves: "); + for (Map.Entry<String, EC_Curve> curve : curves.entrySet()) { + out.append(curve.getKey()); + size--; + if (size > 0) + out.append(", "); + } + out.append(System.lineSeparator()); + } + + Map<String, EC_Key> keys = getObjects(EC_Key.class); + size = keys.size(); + if (size > 0) { + out.append("\t\tKeys: "); + for (Map.Entry<String, EC_Key> key : keys.entrySet()) { + out.append(key.getKey()); + size--; + if (size > 0) + out.append(", "); + } + out.append(System.lineSeparator()); + } + + Map<String, EC_Keypair> keypairs = getObjects(EC_Keypair.class); + size = keypairs.size(); + if (size > 0) { + out.append("\t\tKeypairs: "); + for (Map.Entry<String, EC_Keypair> key : keypairs.entrySet()) { + out.append(key.getKey()); + size--; + if (size > 0) + out.append(", "); + } + out.append(System.lineSeparator()); + } + + Map<String, EC_KAResult> results = getObjects(EC_KAResult.class); + size = results.size(); + if (size > 0) { + out.append("\t\tResults: "); + for (Map.Entry<String, EC_KAResult> result : results.entrySet()) { + out.append(result.getKey()); + size--; + if (size > 0) + out.append(", "); + } + out.append(System.lineSeparator()); + } + return out.toString(); + } + + @Override + public boolean equals(Object obj) { + return obj instanceof EC_Category && Objects.equals(this.name, ((EC_Category) obj).name); + } + + @Override + public int hashCode() { + return this.name.hashCode() ^ this.directory.hashCode(); + } + +} diff --git a/src/cz/crcs/ectester/common/ec/EC_Curve.java b/src/cz/crcs/ectester/common/ec/EC_Curve.java new file mode 100644 index 0000000..173fd29 --- /dev/null +++ b/src/cz/crcs/ectester/common/ec/EC_Curve.java @@ -0,0 +1,132 @@ +package cz.crcs.ectester.common.ec; + +import cz.crcs.ectester.applet.EC_Consts; +import cz.crcs.ectester.common.util.ByteUtil; +import javacard.security.KeyPair; + +import java.math.BigInteger; +import java.security.spec.*; + +/** + * An Elliptic curve, contains parameters Fp/F2M, A, B, G, R, (K)?. + * + * @author Jan Jancar johny@neuromancer.sk + */ +public class EC_Curve extends EC_Params { + private short bits; + private byte field; + private String desc; + + /** + * @param bits + * @param field KeyPair.ALG_EC_FP or KeyPair.ALG_EC_F2M + */ + public EC_Curve(short bits, byte field) { + super(field == KeyPair.ALG_EC_FP ? EC_Consts.PARAMETERS_DOMAIN_FP : EC_Consts.PARAMETERS_DOMAIN_F2M); + this.bits = bits; + this.field = field; + } + + public EC_Curve(String id, short bits, byte field) { + this(bits, field); + this.id = id; + } + + public EC_Curve(String id, short bits, byte field, String desc) { + this(id, bits, field); + this.desc = desc; + } + + public short getBits() { + return bits; + } + + public byte getField() { + return field; + } + + public String getDesc() { + return desc; + } + + @Override + public String toString() { + return "<" + getId() + "> " + (field == KeyPair.ALG_EC_FP ? "Prime" : "Binary") + " field Elliptic curve (" + String.valueOf(bits) + "b)" + (desc == null ? "" : ": " + desc); + } + + public ECParameterSpec toSpec() { + ECField field; + if (this.field == KeyPair.ALG_EC_FP) { + field = new ECFieldFp(new BigInteger(1, getData(0))); + } else { + byte[][] fieldData = getParam(EC_Consts.PARAMETER_F2M); + int m = ByteUtil.getShort(fieldData[0], 0); + int e1 = ByteUtil.getShort(fieldData[1], 0); + int e2 = ByteUtil.getShort(fieldData[2], 0); + int e3 = ByteUtil.getShort(fieldData[3], 0); + int[] powers = new int[]{e1, e2, e3}; + field = new ECFieldF2m(m, powers); + } + + BigInteger a = new BigInteger(1, getParam(EC_Consts.PARAMETER_A)[0]); + BigInteger b = new BigInteger(1, getParam(EC_Consts.PARAMETER_B)[0]); + + EllipticCurve curve = new EllipticCurve(field, a, b); + + byte[][] G = getParam(EC_Consts.PARAMETER_G); + BigInteger gx = new BigInteger(1, G[0]); + BigInteger gy = new BigInteger(1, G[1]); + ECPoint generator = new ECPoint(gx, gy); + + BigInteger n = new BigInteger(1, getParam(EC_Consts.PARAMETER_R)[0]); + + int h = ByteUtil.getShort(getParam(EC_Consts.PARAMETER_K)[0], 0); + + return new ECParameterSpec(curve, generator, n, h); + } + + public static EC_Curve fromSpec(ECParameterSpec spec) { + EllipticCurve curve = spec.getCurve(); + ECField field = curve.getField(); + + short bits = (short) field.getFieldSize(); + byte[][] params; + int paramIndex = 0; + byte fieldType; + if (field instanceof ECFieldFp) { + ECFieldFp primeField = (ECFieldFp) field; + params = new byte[7][]; + params[paramIndex++] = primeField.getP().toByteArray(); + fieldType = KeyPair.ALG_EC_FP; + } else if (field instanceof ECFieldF2m) { + ECFieldF2m binaryField = (ECFieldF2m) field; + params = new byte[10][]; + params[paramIndex] = new byte[2]; + ByteUtil.setShort(params[paramIndex++], 0, (short) binaryField.getM()); + int[] powers = binaryField.getMidTermsOfReductionPolynomial(); + for (int i = 0; i < 3; ++i) { + params[paramIndex] = new byte[2]; + ByteUtil.setShort(params[paramIndex++], 0, (short) powers[i]); + } + fieldType = KeyPair.ALG_EC_F2M; + } else { + throw new IllegalArgumentException("ECParameterSpec with an unknown field."); + } + + ECPoint generator = spec.getGenerator(); + + params[paramIndex++] = curve.getA().toByteArray(); + params[paramIndex++] = curve.getB().toByteArray(); + + params[paramIndex++] = generator.getAffineX().toByteArray(); + params[paramIndex++] = generator.getAffineY().toByteArray(); + + params[paramIndex++] = spec.getOrder().toByteArray(); + params[paramIndex] = new byte[2]; + ByteUtil.setShort(params[paramIndex], 0, (short) spec.getCofactor()); + + EC_Curve result = new EC_Curve(bits, fieldType); + result.readByteArray(params); + return result; + } +} diff --git a/src/cz/crcs/ectester/common/ec/EC_Data.java b/src/cz/crcs/ectester/common/ec/EC_Data.java new file mode 100644 index 0000000..c048ef7 --- /dev/null +++ b/src/cz/crcs/ectester/common/ec/EC_Data.java @@ -0,0 +1,217 @@ +package cz.crcs.ectester.common.ec; + +import cz.crcs.ectester.common.util.ByteUtil; + +import java.io.*; +import java.util.*; +import java.util.regex.Pattern; + +/** + * A list of byte arrays for holding EC data. + * <p> + * The data can be read from a byte array via <code>readBytes()</code>, from a CSV via <code>readCSV()</code>. + * The data can be exported to a byte array via <code>flatten()</code> or to a string array via <code>expand()</code>. + * + * @author Jan Jancar johny@neuromancer.sk + */ +public abstract class EC_Data { + String id; + int count; + byte[][] data; + + private static final Pattern HEX = Pattern.compile("(0x|0X)?[a-fA-F\\d]+"); + + EC_Data() { + } + + EC_Data(int count) { + this.count = count; + this.data = new byte[count][]; + } + + EC_Data(byte[][] data) { + this.count = data.length; + this.data = data; + } + + EC_Data(String id, int count) { + this(count); + this.id = id; + } + + EC_Data(String id, byte[][] data) { + this(data); + this.id = id; + } + + public String getId() { + return id; + } + + public int getCount() { + return count; + } + + public byte[][] getData() { + return data; + } + + public byte[] getData(int index) { + return data[index]; + } + + public boolean hasData() { + return data != null; + } + + public byte[] flatten() { + ByteArrayOutputStream out = new ByteArrayOutputStream(); + for (byte[] param : data) { + byte[] length = new byte[2]; + ByteUtil.setShort(length, 0, (short) param.length); + + out.write(length, 0, 2); + out.write(param, 0, param.length); + } + + return out.toByteArray(); + } + + public String[] expand() { + List<String> out = new ArrayList<>(count); + for (byte[] param : data) { + out.add(ByteUtil.bytesToHex(param, false)); + } + + return out.toArray(new String[out.size()]); + } + + private static byte[] pad(byte[] data) { + if (data.length == 1) { + return new byte[]{(byte) 0, data[0]}; + } else if (data.length == 0 || data.length > 2) { + return data; + } + return null; + } + + private static byte[] parse(String param) { + byte[] data; + if (param.startsWith("0x") || param.startsWith("0X")) { + data = ByteUtil.hexToBytes(param.substring(2)); + } else { + data = ByteUtil.hexToBytes(param); + } + if (data == null) + return new byte[0]; + if (data.length < 2) + return pad(data); + return data; + } + + private boolean readHex(String[] hex) { + if (hex.length != count) { + return false; + } + + for (int i = 0; i < count; ++i) { + this.data[i] = parse(hex[i]); + } + return true; + } + + public boolean readCSV(InputStream in) { + Scanner s = new Scanner(in); + + s.useDelimiter(",|;"); + List<String> data = new LinkedList<>(); + while (s.hasNext()) { + String field = s.next(); + data.add(field.replaceAll("\\s+", "")); + } + + if (data.isEmpty()) { + return false; + } + for (String param : data) { + if (!HEX.matcher(param).matches()) { + return false; + } + } + return readHex(data.toArray(new String[data.size()])); + } + + public boolean readBytes(byte[] bytes) { + if (bytes == null) { + return false; + } + + int offset = 0; + for (int i = 0; i < count; i++) { + if (bytes.length - offset < 2) { + return false; + } + short paramLength = ByteUtil.getShort(bytes, offset); + offset += 2; + if (bytes.length < offset + paramLength) { + return false; + } + data[i] = new byte[paramLength]; + System.arraycopy(bytes, offset, data[i], 0, paramLength); + offset += paramLength; + } + return true; + } + + public boolean readByteArray(byte[][] bytes) { + if (bytes == null || count != bytes.length) { + return false; + } + + for (int i = 0; i < count; ++i) { + data[i] = new byte[bytes[i].length]; + System.arraycopy(bytes[i], 0, data[i], 0, bytes[i].length); + } + return true; + } + + public void writeCSV(OutputStream out) throws IOException { + Writer w = new OutputStreamWriter(out); + w.write(String.join(",", expand())); + w.flush(); + } + + @Override + public String toString() { + return String.join(",", expand()); + } + + @Override + public boolean equals(Object obj) { + if (obj instanceof EC_Data) { + EC_Data other = (EC_Data) obj; + if (this.id != null || other.id != null) { + return Objects.equals(this.id, other.id); + } + + if (this.count != other.count) + return false; + for (int i = 0; i < this.count; ++i) { + if (!Arrays.equals(this.data[i], other.data[i])) { + return false; + } + } + return true; + } else { + return false; + } + } + + @Override + public int hashCode() { + if (this.id != null) { + return this.id.hashCode(); + } + return Arrays.deepHashCode(this.data); + } +} diff --git a/src/cz/crcs/ectester/common/ec/EC_KAResult.java b/src/cz/crcs/ectester/common/ec/EC_KAResult.java new file mode 100644 index 0000000..8a5fcb4 --- /dev/null +++ b/src/cz/crcs/ectester/common/ec/EC_KAResult.java @@ -0,0 +1,65 @@ +package cz.crcs.ectester.common.ec; + +import cz.crcs.ectester.common.util.CardUtil; + +/** + * A result of EC based Key agreement operation. + * + * @author Jan Jancar johny@neuromancer.sk + */ +public class EC_KAResult extends EC_Data { + private String ka; + private String curve; + private String oneKey; + private String otherKey; + + private String desc; + + public EC_KAResult(String ka, String curve, String oneKey, String otherKey) { + super(1); + this.ka = ka; + this.curve = curve; + this.oneKey = oneKey; + this.otherKey = otherKey; + } + + public EC_KAResult(String id, String ka, String curve, String oneKey, String otherKey) { + this(ka, curve, oneKey, otherKey); + this.id = id; + } + + public EC_KAResult(String id, String ka, String curve, String oneKey, String otherKey, String desc) { + this(id, ka, curve, oneKey, otherKey); + this.desc = desc; + } + + public String getKA() { + return ka; + } + + public byte getJavaCardKA() { + return CardUtil.getKA(ka); + } + + public String getCurve() { + return curve; + } + + public String getOneKey() { + return oneKey; + } + + public String getOtherKey() { + return otherKey; + } + + public String getDesc() { + return desc; + } + + @Override + public String toString() { + return "<" + getId() + "> " + ka + " result over " + curve + ", " + oneKey + " + " + otherKey + (desc == null ? "" : ": " + desc); + } + +} diff --git a/src/cz/crcs/ectester/common/ec/EC_Key.java b/src/cz/crcs/ectester/common/ec/EC_Key.java new file mode 100644 index 0000000..a34b0e7 --- /dev/null +++ b/src/cz/crcs/ectester/common/ec/EC_Key.java @@ -0,0 +1,83 @@ +package cz.crcs.ectester.common.ec; + +import cz.crcs.ectester.applet.EC_Consts; + +/** + * An abstract-like EC key. Concrete implementations create a public and private keys. + * + * @author Jan Jancar johny@neuromancer.sk + */ +public class EC_Key extends EC_Params { + + private String curve; + private String desc; + + private EC_Key(short mask, String curve) { + super(mask); + this.curve = curve; + } + + private EC_Key(short mask, String curve, String desc) { + this(mask, curve); + this.desc = desc; + } + + private EC_Key(String id, short mask, String curve, String desc) { + this(mask, curve, desc); + this.id = id; + } + + public String getCurve() { + return curve; + } + + public String getDesc() { + return desc; + } + + /** + * An EC public key, contains the W parameter. + */ + public static class Public extends EC_Key { + + public Public(String curve) { + super(EC_Consts.PARAMETER_W, curve); + } + + public Public(String curve, String desc) { + super(EC_Consts.PARAMETER_W, curve, desc); + } + + public Public(String id, String curve, String desc) { + super(id, EC_Consts.PARAMETER_W, curve, desc); + } + + @Override + public String toString() { + return "<" + getId() + "> EC Public key, over " + getCurve() + (getDesc() == null ? "" : ": " + getDesc()); + } + } + + /** + * An EC private key, contains the S parameter. + */ + public static class Private extends EC_Key { + + public Private(String curve) { + super(EC_Consts.PARAMETER_S, curve); + } + + public Private(String curve, String desc) { + super(EC_Consts.PARAMETER_S, curve, desc); + } + + public Private(String id, String curve, String desc) { + super(id, EC_Consts.PARAMETER_S, curve, desc); + } + + @Override + public String toString() { + return "<" + getId() + "> EC Private key, over " + getCurve() + (getDesc() == null ? "" : ": " + getDesc()); + } + } +} diff --git a/src/cz/crcs/ectester/common/ec/EC_Keypair.java b/src/cz/crcs/ectester/common/ec/EC_Keypair.java new file mode 100644 index 0000000..53632cd --- /dev/null +++ b/src/cz/crcs/ectester/common/ec/EC_Keypair.java @@ -0,0 +1,41 @@ +package cz.crcs.ectester.common.ec; + +import cz.crcs.ectester.applet.EC_Consts; + +/** + * An EC keypair, contains both the W and S parameters. + * + * @author Jan Jancar johny@neuromancer.sk + */ +public class EC_Keypair extends EC_Params { + private String curve; + private String desc; + + public EC_Keypair(String curve) { + super(EC_Consts.PARAMETERS_KEYPAIR); + this.curve = curve; + } + + public EC_Keypair(String curve, String desc) { + this(curve); + this.desc = desc; + } + + public EC_Keypair(String id, String curve, String desc) { + this(curve, desc); + this.id = id; + } + + public String getCurve() { + return curve; + } + + public String getDesc() { + return desc; + } + + @Override + public String toString() { + return "<" + getId() + "> EC Keypair, over " + curve + (desc == null ? "" : ": " + desc); + } +} diff --git a/src/cz/crcs/ectester/common/ec/EC_Params.java b/src/cz/crcs/ectester/common/ec/EC_Params.java new file mode 100644 index 0000000..1c066e7 --- /dev/null +++ b/src/cz/crcs/ectester/common/ec/EC_Params.java @@ -0,0 +1,194 @@ +package cz.crcs.ectester.common.ec; + +import cz.crcs.ectester.applet.EC_Consts; +import cz.crcs.ectester.common.util.ByteUtil; + +import java.io.ByteArrayOutputStream; +import java.util.ArrayList; +import java.util.List; + +/** + * A list of EC parameters, can contain a subset of the Fp/F2M, A, B, G, R, K, W, S parameters. + * + * The set of parameters is uniquely identified by a short bit string. + * The parameters can be exported to a byte array via <code>flatten()</code> or to a comma delimited + * string via <code>expand()</code>. + * @author Jan Jancar johny@neuromancer.sk + */ +public class EC_Params extends EC_Data { + private short params; + + public EC_Params(short params) { + this.params = params; + this.count = numParams(); + this.data = new byte[this.count][]; + } + + public EC_Params(short params, byte[][] data) { + this.params = params; + this.count = data.length; + this.data = data; + } + + public EC_Params(String id, short params) { + this(params); + this.id = id; + } + + public EC_Params(String id, short params, byte[][] data) { + this(params, data); + this.id = id; + } + + public short getParams() { + return params; + } + + public byte[][] getParam(short param) { + if (!hasParam(param)) { + return null; + } + if (Integer.bitCount(param) != 1) { + return null; + } + short paramMask = EC_Consts.PARAMETER_FP; + byte[][] result = null; + int i = 0; + while (paramMask <= EC_Consts.PARAMETER_S) { + short masked = (short) (this.params & param & paramMask); + short shallow = (short) (this.params & paramMask); + if (masked != 0) { + if (masked == EC_Consts.PARAMETER_F2M) { + result = new byte[4][]; + result[0] = data[i].clone(); + result[1] = data[i+1].clone(); + result[2] = data[i+2].clone(); + result[3] = data[i+3].clone(); + break; + } + if (masked == EC_Consts.PARAMETER_G || masked == EC_Consts.PARAMETER_W) { + result = new byte[2][]; + result[0] = data[i].clone(); + result[1] = data[i+1].clone(); + break; + } + result = new byte[1][]; + result[0] = data[i].clone(); + } + if (shallow == EC_Consts.PARAMETER_F2M) { + i += 4; + } else if (shallow == EC_Consts.PARAMETER_G || shallow == EC_Consts.PARAMETER_W) { + i += 2; + } else if (shallow != 0) { + i++; + } + paramMask = (short) (paramMask << 1); + } + return result; + } + + public boolean hasParam(short param) { + return (params & param) != 0; + } + + public int numParams() { + short paramMask = EC_Consts.PARAMETER_FP; + int num = 0; + while (paramMask <= EC_Consts.PARAMETER_S) { + if ((paramMask & params) != 0) { + if (paramMask == EC_Consts.PARAMETER_F2M) { + num += 3; + } + if (paramMask == EC_Consts.PARAMETER_W || paramMask == EC_Consts.PARAMETER_G) { + num += 1; + } + ++num; + } + paramMask = (short) (paramMask << 1); + } + return num; + } + + @Override + public byte[] flatten() { + return flatten(params); + } + + public byte[] flatten(short params) { + ByteArrayOutputStream out = new ByteArrayOutputStream(); + short paramMask = EC_Consts.PARAMETER_FP; + int i = 0; + while (paramMask <= EC_Consts.PARAMETER_S) { + short masked = (short) (this.params & params & paramMask); + short shallow = (short) (this.params & paramMask); + if (masked != 0) { + byte[] param = data[i]; + if (masked == EC_Consts.PARAMETER_F2M) { + //add m, e_1, e_2, e_3 + param = ByteUtil.concatenate(param, data[i + 1]); + if (!ByteUtil.allValue(data[i + 2], (byte) 0)) { + param = ByteUtil.concatenate(param, data[i + 2]); + } + if (!ByteUtil.allValue(data[i + 3], (byte) 0)) { + param = ByteUtil.concatenate(param, data[i + 3]); + } + if (!(param.length == 4 || param.length == 8)) + throw new RuntimeException("PARAMETER_F2M length is not 8.(should be)"); + } + if (masked == EC_Consts.PARAMETER_G || masked == EC_Consts.PARAMETER_W) { + //read another param (the y coord) and put into X962 format. + byte[] y = data[i + 1]; + param = ByteUtil.concatenate(new byte[]{4}, param, y); //<- ugly but works! + } + if (param.length == 0) + throw new RuntimeException("Empty parameter read?"); + + //write length + byte[] length = new byte[2]; + ByteUtil.setShort(length, 0, (short) param.length); + out.write(length, 0, 2); + //write data + out.write(param, 0, param.length); + } + if (shallow == EC_Consts.PARAMETER_F2M) { + i += 4; + } else if (shallow == EC_Consts.PARAMETER_G || shallow == EC_Consts.PARAMETER_W) { + i += 2; + } else if (shallow != 0) { + i++; + } + paramMask = (short) (paramMask << 1); + } + + return (out.size() == 0) ? null : out.toByteArray(); + } + + @Override + public String[] expand() { + List<String> out = new ArrayList<>(); + + short paramMask = EC_Consts.PARAMETER_FP; + int index = 0; + while (paramMask <= EC_Consts.PARAMETER_S) { + short masked = (short) (params & paramMask); + if (masked != 0) { + byte[] param = data[index]; + if (masked == EC_Consts.PARAMETER_F2M) { + for (int i = 0; i < 4; ++i) { + out.add(ByteUtil.bytesToHex(data[index + i], false)); + } + index += 4; + } else if (masked == EC_Consts.PARAMETER_G || masked == EC_Consts.PARAMETER_W) { + out.add(ByteUtil.bytesToHex(param, false)); + out.add(ByteUtil.bytesToHex(data[index + 1], false)); + index += 2; + } else { + out.add(ByteUtil.bytesToHex(param, false)); + index++; + } + } + paramMask = (short) (paramMask << 1); + } + return out.toArray(new String[out.size()]); + } +} |
