diff options
| author | J08nY | 2017-03-26 00:20:29 +0100 |
|---|---|---|
| committer | J08nY | 2017-03-26 00:20:29 +0100 |
| commit | de1736c211dc8d27961ef0495c82d25fbf813e05 (patch) | |
| tree | 34bb31a99e8b82dd707c80ed971d7687bdc023de /src | |
| parent | 66516ffeaca12b9cc9811c1dd948fc2cd2564c29 (diff) | |
| download | ECTester-de1736c211dc8d27961ef0495c82d25fbf813e05.tar.gz ECTester-de1736c211dc8d27961ef0495c82d25fbf813e05.tar.zst ECTester-de1736c211dc8d27961ef0495c82d25fbf813e05.zip | |
Diffstat (limited to 'src')
| -rw-r--r-- | src/cz/crcs/ectester/applet/ECKeyGenerator.java | 2 | ||||
| -rw-r--r-- | src/cz/crcs/ectester/applet/ECKeyTester.java | 5 | ||||
| -rw-r--r-- | src/cz/crcs/ectester/data/EC_Store.java (renamed from src/cz/crcs/ectester/data/EC_Data.java) | 10 | ||||
| -rw-r--r-- | src/cz/crcs/ectester/data/categories.xml | 5 | ||||
| -rw-r--r-- | src/cz/crcs/ectester/data/invalid/curves.xml | 4 | ||||
| -rw-r--r-- | src/cz/crcs/ectester/data/test/keys.xml | 16 | ||||
| -rw-r--r-- | src/cz/crcs/ectester/data/test/secg/secp160r1-dh-kdf.csv | 1 | ||||
| -rw-r--r-- | src/cz/crcs/ectester/data/test/secg/secp160r1-dh-raw.csv | 1 | ||||
| -rw-r--r-- | src/cz/crcs/ectester/data/test/secg/secp160r1-dh-sha1.csv | 1 | ||||
| -rw-r--r-- | src/cz/crcs/ectester/data/test/secg/secp160r1-keyU.csv | 1 | ||||
| -rw-r--r-- | src/cz/crcs/ectester/data/test/secg/secp160r1-keyV.csv | 1 | ||||
| -rw-r--r-- | src/cz/crcs/ectester/reader/ECTester.java | 139 | ||||
| -rw-r--r-- | src/cz/crcs/ectester/reader/ec/EC_Data.java | 135 | ||||
| -rw-r--r-- | src/cz/crcs/ectester/reader/ec/EC_Params.java | 111 |
14 files changed, 275 insertions, 157 deletions
diff --git a/src/cz/crcs/ectester/applet/ECKeyGenerator.java b/src/cz/crcs/ectester/applet/ECKeyGenerator.java index da6142f..b412370 100644 --- a/src/cz/crcs/ectester/applet/ECKeyGenerator.java +++ b/src/cz/crcs/ectester/applet/ECKeyGenerator.java @@ -170,7 +170,7 @@ public class ECKeyGenerator { short i = Util.makeShort(data[(short) (offset + 2)], data[(short) (offset + 3)]); if ((key & EC_Consts.KEY_PUBLIC) != 0) ecPublicKey.setFieldF2M(i); if ((key & EC_Consts.KEY_PRIVATE) != 0) ecPrivateKey.setFieldF2M(i); - } else if (length == 8){ + } else if (length == 8) { short i1 = Util.makeShort(data[(short) (offset + 2)], data[(short) (offset + 3)]); short i2 = Util.makeShort(data[(short) (offset + 4)], data[(short) (offset + 5)]); short i3 = Util.makeShort(data[(short) (offset + 6)], data[(short) (offset + 7)]); diff --git a/src/cz/crcs/ectester/applet/ECKeyTester.java b/src/cz/crcs/ectester/applet/ECKeyTester.java index 057d357..7ef6150 100644 --- a/src/cz/crcs/ectester/applet/ECKeyTester.java +++ b/src/cz/crcs/ectester/applet/ECKeyTester.java @@ -3,7 +3,10 @@ package cz.crcs.ectester.applet; import javacard.framework.CardRuntimeException; import javacard.framework.ISO7816; -import javacard.security.*; +import javacard.security.ECPrivateKey; +import javacard.security.ECPublicKey; +import javacard.security.KeyAgreement; +import javacard.security.Signature; /** * Class capable of testing ECDH/C and ECDSA. diff --git a/src/cz/crcs/ectester/data/EC_Data.java b/src/cz/crcs/ectester/data/EC_Store.java index 98b2d59..60a1065 100644 --- a/src/cz/crcs/ectester/data/EC_Data.java +++ b/src/cz/crcs/ectester/data/EC_Store.java @@ -29,13 +29,13 @@ import java.util.Map; /** * @author Jan Jancar johny@neuromancer.sk */ -public class EC_Data { +public class EC_Store { private DocumentBuilder db; private Map<String, EC_Category> categories; - public EC_Data() { + public EC_Store() { DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance(); try { @@ -49,17 +49,17 @@ public class EC_Data { db.setErrorHandler(new ErrorHandler() { @Override public void warning(SAXParseException exception) throws SAXException { - System.err.println("EC_Data | Warning : " + exception); + System.err.println("EC_Store | Warning : " + exception); } @Override public void error(SAXParseException exception) throws SAXException { - System.err.println("EC_Data | Error : " + exception); + System.err.println("EC_Store | Error : " + exception); } @Override public void fatalError(SAXParseException exception) throws SAXException { - System.err.println("EC_Data | Fatal : " + exception); + System.err.println("EC_Store | Fatal : " + exception); } }); diff --git a/src/cz/crcs/ectester/data/categories.xml b/src/cz/crcs/ectester/data/categories.xml index 5913d42..d0c9f39 100644 --- a/src/cz/crcs/ectester/data/categories.xml +++ b/src/cz/crcs/ectester/data/categories.xml @@ -31,4 +31,9 @@ <directory>wrong</directory> <desc>Wrong field curves. These should definitely give an error when used. Since the "prime" used for the field are not prime, and the field polynomials are also not irreducible. Simply put these parameters don't specify a valid elliptic curve.</desc> </category> + <category> + <name>test</name> + <directory>test</directory> + <desc>Test vectors</desc> + </category> </categories>
\ No newline at end of file diff --git a/src/cz/crcs/ectester/data/invalid/curves.xml b/src/cz/crcs/ectester/data/invalid/curves.xml new file mode 100644 index 0000000..e87269f --- /dev/null +++ b/src/cz/crcs/ectester/data/invalid/curves.xml @@ -0,0 +1,4 @@ +<?xml version="1.0" encoding="utf-8" ?> +<curves xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="../schema.xsd"> +</curves>
\ No newline at end of file diff --git a/src/cz/crcs/ectester/data/test/keys.xml b/src/cz/crcs/ectester/data/test/keys.xml new file mode 100644 index 0000000..56fc4e2 --- /dev/null +++ b/src/cz/crcs/ectester/data/test/keys.xml @@ -0,0 +1,16 @@ +<?xml version="1.0" encoding="utf-8" ?> +<keys xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="../schema.xsd" + category="test" + desc="Test vectors"> + <keypair> + <id>secp160r1-U</id> + <file>secg/secp160r1-keyU.csv</file> + <curve>secg/secp160r1</curve> + </keypair> + <keypair> + <id>secp160r1-V</id> + <file>secg/secp160r1-keyV.csv</file> + <curve>secg/secp160r1</curve> + </keypair> +</keys>
\ No newline at end of file diff --git a/src/cz/crcs/ectester/data/test/secg/secp160r1-dh-kdf.csv b/src/cz/crcs/ectester/data/test/secg/secp160r1-dh-kdf.csv new file mode 100644 index 0000000..e8060e1 --- /dev/null +++ b/src/cz/crcs/ectester/data/test/secg/secp160r1-dh-kdf.csv @@ -0,0 +1 @@ +744AB703F5BC082E59185F6D049D2D367DB245C2 diff --git a/src/cz/crcs/ectester/data/test/secg/secp160r1-dh-raw.csv b/src/cz/crcs/ectester/data/test/secg/secp160r1-dh-raw.csv new file mode 100644 index 0000000..3eac8d9 --- /dev/null +++ b/src/cz/crcs/ectester/data/test/secg/secp160r1-dh-raw.csv @@ -0,0 +1 @@ +CA7C0F8C3FFA87A96E1B74AC8E6AF594347BB40A diff --git a/src/cz/crcs/ectester/data/test/secg/secp160r1-dh-sha1.csv b/src/cz/crcs/ectester/data/test/secg/secp160r1-dh-sha1.csv new file mode 100644 index 0000000..97735e7 --- /dev/null +++ b/src/cz/crcs/ectester/data/test/secg/secp160r1-dh-sha1.csv @@ -0,0 +1 @@ +D248313E865A1AE677782B54B24D8ABAF11A53C2 diff --git a/src/cz/crcs/ectester/data/test/secg/secp160r1-keyU.csv b/src/cz/crcs/ectester/data/test/secg/secp160r1-keyU.csv new file mode 100644 index 0000000..bbf9e62 --- /dev/null +++ b/src/cz/crcs/ectester/data/test/secg/secp160r1-keyU.csv @@ -0,0 +1 @@ +51B4496FECC406ED0E75A24A3C03206251419DC0,C28DCB4B73A514B468D793894F381CCC1756AA6C,AA374FFC3CE144E6B073307972CB6D57B2A4E982
\ No newline at end of file diff --git a/src/cz/crcs/ectester/data/test/secg/secp160r1-keyV.csv b/src/cz/crcs/ectester/data/test/secg/secp160r1-keyV.csv new file mode 100644 index 0000000..6d9bc31 --- /dev/null +++ b/src/cz/crcs/ectester/data/test/secg/secp160r1-keyV.csv @@ -0,0 +1 @@ +49B41E0E9C0369C2328739D90F63D56707C6E5BC,26E008B567015ED96D232A03111C3EDC0E9C8F83,45FB58A92A17AD4B15101C66E74F277E2B460866 diff --git a/src/cz/crcs/ectester/reader/ECTester.java b/src/cz/crcs/ectester/reader/ECTester.java index 2f26275..247a260 100644 --- a/src/cz/crcs/ectester/reader/ECTester.java +++ b/src/cz/crcs/ectester/reader/ECTester.java @@ -24,7 +24,7 @@ package cz.crcs.ectester.reader; import cz.crcs.ectester.applet.ECTesterApplet; import cz.crcs.ectester.applet.EC_Consts; import cz.crcs.ectester.data.EC_Category; -import cz.crcs.ectester.data.EC_Data; +import cz.crcs.ectester.data.EC_Store; import cz.crcs.ectester.reader.ec.EC_Curve; import cz.crcs.ectester.reader.ec.EC_Key; import cz.crcs.ectester.reader.ec.EC_Keypair; @@ -47,7 +47,7 @@ public class ECTester { private CardMngr cardManager; private DirtyLogger systemOutLogger; - private EC_Data dataDB; + private EC_Store dataStore; //Options private int optBits; @@ -108,7 +108,7 @@ public class ECTester { return; } - dataDB = new EC_Data(); + dataStore = new EC_Store(); //if list, print and quit if (cli.hasOption("list-named")) { list(); @@ -462,7 +462,7 @@ public class ECTester { * List categories and named curves. */ private void list() { - Map<String, EC_Category> categories = dataDB.getCategories(); + Map<String, EC_Category> categories = dataStore.getCategories(); for (EC_Category cat : categories.values()) { System.out.println("\t- " + cat.getName() + ": " + (cat.getDesc() == null ? "" : cat.getDesc())); @@ -597,34 +597,16 @@ public class ECTester { List<Command> commands = new LinkedList<>(); if (optTestCase.equalsIgnoreCase("default")) { - if (optAll) { - if (optNamedCurve != null) { - Map<String, EC_Curve> curves = dataDB.getObjects(EC_Curve.class, optNamedCurve); - if (optPrimeField) { - for (Map.Entry<String, EC_Curve> entry : curves.entrySet()) { - EC_Curve curve = entry.getValue(); - if (curve.getField() == KeyPair.ALG_EC_FP) { - commands.add(new Command.Allocate(cardManager, ECTesterApplet.KEYPAIR_BOTH, curve.getBits(), KeyPair.ALG_EC_FP)); - byte[] external = curve.flatten(); - commands.add(new Command.Set(cardManager, ECTesterApplet.KEYPAIR_BOTH, EC_Consts.CURVE_external, curve.getParams(), external)); - commands.addAll(testCurve()); - commands.add(new Command.Cleanup(cardManager)); - } - } - } - if (optBinaryField) { - for (Map.Entry<String, EC_Curve> entry : curves.entrySet()) { - EC_Curve curve = entry.getValue(); - if (curve.getField() == KeyPair.ALG_EC_F2M) { - commands.add(new Command.Allocate(cardManager, ECTesterApplet.KEYPAIR_BOTH, curve.getBits(), KeyPair.ALG_EC_F2M)); - byte[] external = curve.flatten(); - commands.add(new Command.Set(cardManager, ECTesterApplet.KEYPAIR_BOTH, EC_Consts.CURVE_external, curve.getParams(), external)); - commands.addAll(testCurve()); - commands.add(new Command.Cleanup(cardManager)); - } - } - } - } else { + + if (optNamedCurve != null) { + if (optPrimeField) { + commands.addAll(testCurves(optNamedCurve, KeyPair.ALG_EC_FP)); + } + if (optBinaryField) { + commands.addAll(testCurves(optNamedCurve, KeyPair.ALG_EC_F2M)); + } + } else { + if (optAll) { if (optPrimeField) { //iterate over prime curve sizes used: EC_Consts.FP_SIZES for (short keyLength : EC_Consts.FP_SIZES) { @@ -643,32 +625,41 @@ public class ECTester { commands.add(new Command.Cleanup(cardManager)); } } - } - } else { - if (optPrimeField) { - commands.add(new Command.Allocate(cardManager, ECTesterApplet.KEYPAIR_BOTH, (short) optBits, KeyPair.ALG_EC_FP)); - commands.addAll(prepareCurve(ECTesterApplet.KEYPAIR_BOTH, (short) optBits, KeyPair.ALG_EC_FP)); - commands.addAll(testCurve()); - commands.add(new Command.Cleanup(cardManager)); - } + } else { + if (optPrimeField) { + commands.add(new Command.Allocate(cardManager, ECTesterApplet.KEYPAIR_BOTH, (short) optBits, KeyPair.ALG_EC_FP)); + commands.addAll(prepareCurve(ECTesterApplet.KEYPAIR_BOTH, (short) optBits, KeyPair.ALG_EC_FP)); + commands.addAll(testCurve()); + commands.add(new Command.Cleanup(cardManager)); + } - if (optBinaryField) { - commands.add(new Command.Allocate(cardManager, ECTesterApplet.KEYPAIR_BOTH, (short) optBits, KeyPair.ALG_EC_F2M)); - commands.addAll(prepareCurve(ECTesterApplet.KEYPAIR_BOTH, (short) optBits, KeyPair.ALG_EC_F2M)); - commands.addAll(testCurve()); - commands.add(new Command.Cleanup(cardManager)); + if (optBinaryField) { + commands.add(new Command.Allocate(cardManager, ECTesterApplet.KEYPAIR_BOTH, (short) optBits, KeyPair.ALG_EC_F2M)); + commands.addAll(prepareCurve(ECTesterApplet.KEYPAIR_BOTH, (short) optBits, KeyPair.ALG_EC_F2M)); + commands.addAll(testCurve()); + commands.add(new Command.Cleanup(cardManager)); + } } } } else if (optTestCase.equalsIgnoreCase("wrong")) { - + if (optPrimeField) { + commands.addAll(testCurves("wrong", KeyPair.ALG_EC_FP)); + } + if (optBinaryField) { + commands.addAll(testCurves("wrong", KeyPair.ALG_EC_F2M)); + } } else if (optTestCase.equalsIgnoreCase("non-prime")) { + } else if (optTestCase.equalsIgnoreCase("smallpub")) { + } else if (optTestCase.equalsIgnoreCase("invalid")) { } List<Response> test = Command.sendAll(commands); systemOutLogger.println(Response.toString(test)); + + // } /** @@ -685,15 +676,14 @@ public class ECTester { systemOutLogger.println(Response.toString(prepare)); + byte pubkey = (optAnyPublic || optAnyKey) ? ECTesterApplet.KEYPAIR_REMOTE : ECTesterApplet.KEYPAIR_LOCAL; + byte privkey = (optAnyPrivate || optAnyKey) ? ECTesterApplet.KEYPAIR_REMOTE : ECTesterApplet.KEYPAIR_LOCAL; + List<Command> generate = new LinkedList<>(); + generate.add(new Command.Generate(cardManager, ECTesterApplet.KEYPAIR_BOTH)); if (optAnyPublic || optAnyPrivate || optAnyKey) { - generate.add(new Command.Generate(cardManager, ECTesterApplet.KEYPAIR_LOCAL)); generate.add(prepareKey(ECTesterApplet.KEYPAIR_REMOTE)); - } else { - generate.add(new Command.Generate(cardManager, ECTesterApplet.KEYPAIR_BOTH)); } - byte pubkey = (optAnyPublic || optAnyKey) ? ECTesterApplet.KEYPAIR_REMOTE : ECTesterApplet.KEYPAIR_LOCAL; - byte privkey = (optAnyPrivate || optAnyKey) ? ECTesterApplet.KEYPAIR_REMOTE : ECTesterApplet.KEYPAIR_LOCAL; FileWriter out = null; if (optOutput != null) { @@ -816,7 +806,7 @@ public class ECTester { } else if (optNamedCurve != null) { // Set a named curve. // parse optNamedCurve -> cat / id | cat | id - EC_Curve curve = dataDB.getObject(EC_Curve.class, optNamedCurve); + EC_Curve curve = dataStore.getObject(EC_Curve.class, optNamedCurve); if (curve == null) { throw new IOException("Curve could no be found."); } @@ -873,7 +863,7 @@ public class ECTester { keypair.readCSV(in); in.close(); } else { - keypair = dataDB.getObject(EC_Keypair.class, optNamedKey); + keypair = dataStore.getObject(EC_Keypair.class, optNamedKey); } data = keypair.flatten(); @@ -892,12 +882,15 @@ public class ECTester { pub.readCSV(in); in.close(); } else { - pub = dataDB.getObject(EC_Key.Public.class, optNamedPublic); + pub = dataStore.getObject(EC_Key.Public.class, optNamedPublic); + if (pub == null) { + pub = dataStore.getObject(EC_Keypair.class, optNamedPublic); + } } - byte[] pubkey = pub.flatten(); + byte[] pubkey = pub.flatten(EC_Consts.PARAMETER_W); if (pubkey == null) { - throw new IOException("Couldn't read the key file correctly."); + throw new IOException("Couldn't read the public key file correctly."); } data = pubkey; } @@ -911,12 +904,15 @@ public class ECTester { priv.readCSV(in); in.close(); } else { - priv = dataDB.getObject(EC_Key.Public.class, optNamedPrivate); + priv = dataStore.getObject(EC_Key.Public.class, optNamedPrivate); + if (priv == null) { + priv = dataStore.getObject(EC_Keypair.class, optNamedPrivate); + } } - byte[] privkey = priv.flatten(); + byte[] privkey = priv.flatten(EC_Consts.PARAMETER_S); if (privkey == null) { - throw new IOException("Couldn't read the key file correctly."); + throw new IOException("Couldn't read the private key file correctly."); } data = Util.concatenate(data, privkey); } @@ -939,6 +935,31 @@ public class ECTester { return commands; } + /** + * @param category + * @param field + * @return + * @throws IOException + */ + private List<Command> testCurves(String category, byte field) throws IOException { + List<Command> commands = new LinkedList<>(); + Map<String, EC_Curve> curves = dataStore.getObjects(EC_Curve.class, category); + if (curves == null) + return commands; + for (Map.Entry<String, EC_Curve> entry : curves.entrySet()) { + EC_Curve curve = entry.getValue(); + if (curve.getField() == field && (curve.getBits() == optBits || optAll)) { + commands.add(new Command.Allocate(cardManager, ECTesterApplet.KEYPAIR_BOTH, curve.getBits(), field)); + byte[] external = curve.flatten(); + commands.add(new Command.Set(cardManager, ECTesterApplet.KEYPAIR_BOTH, EC_Consts.CURVE_external, curve.getParams(), external)); + commands.addAll(testCurve()); + commands.add(new Command.Cleanup(cardManager)); + } + } + + return commands; + } + public static void main(String[] args) { ECTester app = new ECTester(); app.run(args); diff --git a/src/cz/crcs/ectester/reader/ec/EC_Data.java b/src/cz/crcs/ectester/reader/ec/EC_Data.java new file mode 100644 index 0000000..c1fb54c --- /dev/null +++ b/src/cz/crcs/ectester/reader/ec/EC_Data.java @@ -0,0 +1,135 @@ +package cz.crcs.ectester.reader.ec; + +import cz.crcs.ectester.reader.Util; + +import java.io.*; +import java.util.ArrayList; +import java.util.LinkedList; +import java.util.List; +import java.util.Scanner; +import java.util.regex.Pattern; + +/** + * @author Jan Jancar johny@neuromancer.sk + */ +public class EC_Data { + private static final Pattern hex = Pattern.compile("(0x|0X)?[a-fA-F\\d]+"); + + int count; + byte[][] data; + + EC_Data() { + } + + public EC_Data(int count) { + this.count = count; + this.data = new byte[count][]; + } + + public EC_Data(byte[][] data) { + this.count = data.length; + this.data = data; + } + + public byte[][] getData() { + return data; + } + + public boolean hasData() { + return data != null; + } + + public byte[] flatten() { + ByteArrayOutputStream out = new ByteArrayOutputStream(); + for (byte[] param : data) { + byte[] length = new byte[2]; + Util.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(Util.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 = Util.hexToBytes(param.substring(2)); + } else { + data = Util.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[] data) { + //TODO + return false; + } + + public void writeCSV(OutputStream out) throws IOException { + String[] hex = expand(); + Writer w = new OutputStreamWriter(out); + for (int i = 0; i < hex.length; ++i) { + w.write(hex[i]); + if (i < hex.length - 1) { + w.write(","); + } + } + w.flush(); + } +} diff --git a/src/cz/crcs/ectester/reader/ec/EC_Params.java b/src/cz/crcs/ectester/reader/ec/EC_Params.java index fa5515c..00747b1 100644 --- a/src/cz/crcs/ectester/reader/ec/EC_Params.java +++ b/src/cz/crcs/ectester/reader/ec/EC_Params.java @@ -3,29 +3,25 @@ package cz.crcs.ectester.reader.ec; import cz.crcs.ectester.applet.EC_Consts; import cz.crcs.ectester.reader.Util; -import java.io.*; +import java.io.ByteArrayOutputStream; import java.util.ArrayList; -import java.util.LinkedList; import java.util.List; -import java.util.Scanner; -import java.util.regex.Pattern; /** * @author Jan Jancar johny@neuromancer.sk */ -public class EC_Params { - private static final Pattern hex = Pattern.compile("(0x|0X)?[a-fA-F\\d]+"); - +public class EC_Params extends EC_Data { private short params; - private byte[][] data; public EC_Params(short params) { this.params = params; - this.data = new byte[numParams()][]; + 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; } @@ -45,7 +41,7 @@ public class EC_Params { if (paramMask == EC_Consts.PARAMETER_F2M) { num += 3; } - if (paramMask == EC_Consts.PARAMETER_W || paramMask == EC_Consts.PARAMETER_G){ + if (paramMask == EC_Consts.PARAMETER_W || paramMask == EC_Consts.PARAMETER_G) { num += 1; } ++num; @@ -55,32 +51,29 @@ public class EC_Params { return num; } - public byte[][] getData() { - return data; - } - - public boolean hasData() { - return data != null; + @Override + public byte[] flatten() { + return flatten(params); } - public byte[] flatten() { + 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) (params & paramMask); + 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 = Util.concatenate(param, data[i + 1], data[i + 2], data[i + 3]); - i += 3; if (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]; + byte[] y = data[i + 1]; param = Util.concatenate(new byte[]{4}, param, y); //<- ugly but works! } if (param.length == 0) @@ -92,6 +85,12 @@ public class EC_Params { 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); @@ -100,6 +99,7 @@ public class EC_Params { return (out.size() == 0) ? null : out.toByteArray(); } + @Override public String[] expand() { List<String> out = new ArrayList<>(); @@ -136,75 +136,4 @@ public class EC_Params { 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 = Util.hexToBytes(param.substring(2)); - } else { - data = Util.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 != numParams()) { - return false; - } - - for (int i = 0; i < numParams(); ++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<String>(); - 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 void writeCSV(OutputStream out) throws IOException { - String[] hex = expand(); - Writer w = new OutputStreamWriter(out); - for (int i = 0; i < hex.length; ++i) { - w.write(hex[i]); - if (i < hex.length - 1) { - w.write(","); - } - } - w.flush(); - } - - public boolean readBytes(byte[] data) { - //TODO - return false; - } } |
