public GroupElement[] transform(final GroupElement cloned) throws InvalidPatternException { // moved cloned to up // final GroupElement cloned = (GroupElement) and.clone(); processTree(cloned); cloned.pack(); GroupElement[] ands; // is top element an AND? if (cloned.isAnd()) { // Yes, so just return it ands = new GroupElement[] {cloned}; } else if (cloned.isOr()) { // it is an OR, so each child is an AND branch ands = splitOr(cloned); } else { // no, so just wrap into an AND final GroupElement wrapper = GroupElementFactory.newAndInstance(); wrapper.addChild(cloned); ands = new GroupElement[] {wrapper}; } for (int i = 0; i < ands.length; i++) { // fix the cloned declarations this.fixClonedDeclarations(ands[i]); ands[i].setRoot(true); } return ands; }
/** Test method for {@link GroupElement#cmov(GroupElement, int)}. */ @Test public void testCmov() { GroupElement a = curve.getZero(GroupElement.Representation.PRECOMP); GroupElement b = GroupElement.precomp(curve, TWO, ZERO, TEN); assertThat(a.cmov(b, 0), is(equalTo(a))); assertThat(a.cmov(b, 1), is(equalTo(b))); }
/** * Tests {@link GroupElement#GroupElement(Curve, byte[])} and {@link GroupElement#toByteArray()} * against valid public keys. */ @Test public void testToAndFromByteArray() { GroupElement t; for (Ed25519TestVectors.TestTuple testCase : Ed25519TestVectors.testCases) { t = new GroupElement(curve, testCase.pk); assertThat( "Test case " + testCase.caseNum + " failed", t.toByteArray(), is(equalTo(testCase.pk))); } }
@Test(expected = IllegalArgumentException.class) public void toCachedThrowsIfGroupElementHasP1P1Representation() { // Arrange: final GroupElement g = MathUtils.toRepresentation( MathUtils.getRandomGroupElement(), GroupElement.Representation.P1P1); // Assert: g.toCached(); }
@Test public void isOnCurveReturnsTrueForPointsOnTheCurve() { for (int i = 0; i < 100; i++) { // Arrange: final GroupElement g = MathUtils.getRandomGroupElement(); // Assert: Assert.assertThat(g.isOnCurve(), IsEqual.equalTo(true)); } }
@Test(expected = IllegalArgumentException.class) public void toP3ThrowsIfGroupElementHasPrecompRepresentation() { // Arrange: final GroupElement g = MathUtils.toRepresentation( MathUtils.getRandomGroupElement(), GroupElement.Representation.PRECOMP); // Assert: g.toP3(); }
/** * Traverses a Tree, during the process it transforms Or nodes moving the upwards and it removes * duplicate logic statement, this does not include Not nodes. * * <p>Traversal involves three levels the graph for each iteration. The first level is the current * node, this node will not be transformed, instead what we are interested in are the children of * the current node (called the parent nodes) and the children of those parents (call the child * nodes). * * @param ce */ protected void processTree(final GroupElement ce) throws InvalidPatternException { boolean hasChildOr = false; // first we elimininate any redundancy ce.pack(); Object[] children = (Object[]) ce.getChildren().toArray(); for (Object aChildren : children) { if (aChildren instanceof GroupElement) { final GroupElement child = (GroupElement) aChildren; processTree(child); if ((child.isOr() || child.isAnd()) && child.getType() == ce.getType()) { child.pack(ce); } else if (child.isOr()) { hasChildOr = true; } } } if (hasChildOr) { applyOrTransformation(ce); } }
/** * Traverses a Tree, during the process it transforms Or nodes moving the upwards and it removes * duplicate logic statement, this does not include Not nodes. * * <p>Traversal involves three levels the graph for each iteration. The first level is the current * node, this node will not be transformed, instead what we are interested in are the children of * the current node (called the parent nodes) and the children of those parents (call the child * nodes). */ private void processTree(final GroupElement ce, boolean[] result) throws InvalidPatternException { boolean hasChildOr = false; // first we elimininate any redundancy ce.pack(); for (Object child : ce.getChildren().toArray()) { if (child instanceof GroupElement) { final GroupElement group = (GroupElement) child; processTree(group, result); if ((group.isOr() || group.isAnd()) && group.getType() == ce.getType()) { group.pack(ce); } else if (group.isOr()) { hasChildOr = true; } } else if (child instanceof NamedConsequence) { result[0] = true; } else if (child instanceof Pattern && ((Pattern) child).getObjectType().isEvent()) { result[1] = true; } } if (hasChildOr) { applyOrTransformation(ce); } }
@Test public void scalarMultiplyBasePointWithZeroReturnsNeutralElement() { // Arrange: final GroupElement basePoint = ed25519.getB(); // Act: final GroupElement g = basePoint.scalarMultiply(curve.getField().ZERO.toByteArray()); // Assert: Assert.assertThat(curve.getZero(GroupElement.Representation.P3), IsEqual.equalTo(g)); }
void applyOrTransformation(final GroupElement parent) throws InvalidPatternException { final Transformation transformation = this.orTransformations.get(parent.getType()); if (transformation == null) { throw new RuntimeException( "applyOrTransformation could not find transformation for parent '" + parent.getType() + "' and child 'OR'"); } transformation.transform(parent); }
@Test public void scalarMultiplyBasePointWithOneReturnsBasePoint() { // Arrange: final GroupElement basePoint = ed25519.getB(); // Act: final GroupElement g = basePoint.scalarMultiply(curve.getField().ONE.toByteArray()); // Assert: Assert.assertThat(basePoint, IsEqual.equalTo(g)); }
public void transform(final GroupElement parent) throws InvalidPatternException { final List orsList = new ArrayList(); // must keep order, so, using array final Object[] others = new Object[parent.getChildren().size()]; // first we split children as OR or not OR int permutations = 1; int index = 0; for (final RuleConditionElement child : parent.getChildren()) { if ((child instanceof GroupElement) && ((GroupElement) child).isOr()) { permutations *= ((GroupElement) child).getChildren().size(); orsList.add(child); } else { others[index] = child; } index++; } // transform parent into an OR parent.setType(GroupElement.OR); parent.getChildren().clear(); // prepare arrays and indexes to calculate permutation final GroupElement[] ors = (GroupElement[]) orsList.toArray(new GroupElement[orsList.size()]); final int[] indexes = new int[ors.length]; // now we know how many permutations we will have, so create it for (int i = 1; i <= permutations; i++) { final GroupElement and = GroupElementFactory.newAndInstance(); // create the actual permutations int mod = 1; for (int j = ors.length - 1; j >= 0; j--) { // we must insert at the beginning to keep the order and.getChildren().add(0, ors[j].getChildren().get(indexes[j]).clone()); if ((i % mod) == 0) { indexes[j] = (indexes[j] + 1) % ors[j].getChildren().size(); } mod *= ors[j].getChildren().size(); } // elements originally outside OR will be in every permutation, so add them // in their original position for (int j = 0; j < others.length; j++) { if (others[j] != null) { // always add clone of them to avoid offset conflicts in declarations // HERE IS THE MESSY PROBLEM: need to change further references to the appropriate // cloned ref and.getChildren().add(j, ((RuleConditionElement) others[j]).clone()); } } parent.addChild(and); } // remove duplications parent.pack(); }
protected GroupElement[] splitOr(final GroupElement cloned) { GroupElement[] ands = new GroupElement[cloned.getChildren().size()]; int i = 0; for (final RuleConditionElement branch : cloned.getChildren()) { if ((branch instanceof GroupElement) && (((GroupElement) branch).isAnd())) { ands[i++] = (GroupElement) branch; } else { ands[i] = GroupElementFactory.newAndInstance(); ands[i].addChild(branch); i++; } } return ands; }
@Test public void dblReturnsExpectedResult() { for (int i = 0; i < 1000; i++) { // Arrange: final GroupElement g = MathUtils.getRandomGroupElement(); // Act: final GroupElement h1 = g.dbl(); final GroupElement h2 = MathUtils.doubleGroupElement(g); // Assert: Assert.assertThat(h2, IsEqual.equalTo(h1)); } }
@Test public void subReturnsExpectedResult() { for (int i = 0; i < 1000; i++) { // Arrange: final GroupElement g1 = MathUtils.getRandomGroupElement(); final GroupElement g2 = MathUtils.getRandomGroupElement(); // Act: final GroupElement h1 = g1.sub(g2.toCached()); final GroupElement h2 = MathUtils.addGroupElements(g1, MathUtils.negateGroupElement(g2)); // Assert: Assert.assertThat(h2, IsEqual.equalTo(h1)); } }
@Test public void constructorUsingByteArrayReturnsExpectedResult() { for (int i = 0; i < 100; i++) { // Arrange: final GroupElement g = MathUtils.getRandomGroupElement(); final byte[] bytes = g.toByteArray(); // Act: final GroupElement h1 = new GroupElement(curve, bytes); final GroupElement h2 = MathUtils.toGroupElement(bytes); // Assert: Assert.assertThat(h1, IsEqual.equalTo(h2)); } }
// This test is slow (~6s) due to math utils using an inferior algorithm to calculate the result. @Test public void scalarMultiplyBasePointReturnsExpectedResult() { for (int i = 0; i < 100; i++) { // Arrange: final GroupElement basePoint = ed25519.getB(); final FieldElement f = MathUtils.getRandomFieldElement(); // Act: final GroupElement g = basePoint.scalarMultiply(f.toByteArray()); final GroupElement h = MathUtils.scalarMultiplyGroupElement(basePoint, f); // Assert: Assert.assertThat(g, IsEqual.equalTo(h)); } }
@Test public void toByteArrayReturnsExpectedResult() { for (int i = 0; i < 100; i++) { // Arrange: final GroupElement g = MathUtils.getRandomGroupElement(); // Act: final byte[] gBytes = g.toByteArray(); final byte[] bytes = MathUtils.toByteArray(MathUtils.toBigInteger(g.getY())); if (MathUtils.toBigInteger(g.getX()).mod(new BigInteger("2")).equals(BigInteger.ONE)) { bytes[31] |= 0x80; } // Assert: Assert.assertThat(Arrays.equals(gBytes, bytes), IsEqual.equalTo(true)); } }
private GroupElement getExtendedLhs(Rule rule, GroupElement fromChild) { // combine rules LHS with Parent "Extends" final GroupElement lhs = rule.lhsRoot.cloneOnlyGroup(); // use the children passed from prior child rules, and combine with current LHS (at the end) if (null != fromChild) { // Have GroupElement from a child rule, so combine it lhs.getChildren().addAll(fromChild.getChildren()); } // move recursively up the tree if (rule.parent != null) { return getExtendedLhs(rule.parent, lhs); } // at the top of the tree, return combined LHS // TODO Merge LHS for performace return lhs; }
public GroupElement[] transform(final GroupElement cloned, Map<String, Class<?>> globals) throws InvalidPatternException { // moved cloned to up // final GroupElement cloned = (GroupElement) and.clone(); boolean hasNamedConsequenceAndIsStream = processTree(cloned); cloned.pack(); GroupElement[] ands; // is top element an AND? if (cloned.isAnd()) { // Yes, so just return it ands = new GroupElement[] {cloned}; } else if (cloned.isOr()) { // it is an OR, so each child is an AND branch ands = splitOr(cloned); } else { // no, so just wrap into an AND final GroupElement wrapper = GroupElementFactory.newAndInstance(); wrapper.addChild(cloned); ands = new GroupElement[] {wrapper}; } for (GroupElement and : ands) { // fix the cloned declarations this.fixClonedDeclarations(and, globals); and.setRoot(true); } return hasNamedConsequenceAndIsStream ? processNamedConsequences(ands) : ands; }
/** Test method for {@link GroupElement#toP2()}. */ @Test public void testToP2() { GroupElement p3zero = curve.getZero(GroupElement.Representation.P3); GroupElement t = p3zero.toP2(); assertThat(t.repr, is(GroupElement.Representation.P2)); assertThat(t.X, is(p3zero.X)); assertThat(t.Y, is(p3zero.Y)); assertThat(t.Z, is(p3zero.Z)); assertThat(t.T, is((FieldElement) null)); GroupElement B = ed25519.getB(); t = B.toP2(); assertThat(t.repr, is(GroupElement.Representation.P2)); assertThat(t.X, is(B.X)); assertThat(t.Y, is(B.Y)); assertThat(t.Z, is(B.Z)); assertThat(t.T, is((FieldElement) null)); }
/** Test method for {@link GroupElement#p2(Curve, FieldElement, FieldElement, FieldElement)}. */ @Test public void testP2() { final GroupElement t = GroupElement.p2(curve, ZERO, ONE, ONE); assertThat(t.curve, is(equalTo(curve))); assertThat(t.repr, is(GroupElement.Representation.P2)); assertThat(t.X, is(ZERO)); assertThat(t.Y, is(ONE)); assertThat(t.Z, is(ONE)); assertThat(t.T, is((FieldElement) null)); }
/** * Test method for {@link GroupElement#cached(Curve, FieldElement, FieldElement, FieldElement, * FieldElement)}. */ @Test public void testCached() { final GroupElement t = GroupElement.cached(curve, ONE, ONE, ONE, ZERO); assertThat(t.curve, is(equalTo(curve))); assertThat(t.repr, is(GroupElement.Representation.CACHED)); assertThat(t.X, is(ONE)); assertThat(t.Y, is(ONE)); assertThat(t.Z, is(ONE)); assertThat(t.T, is(ZERO)); }
/** * Test method for {@link GroupElement#p1p1(Curve, FieldElement, FieldElement, FieldElement, * FieldElement)}. */ @Test public void testP1p1() { final GroupElement t = GroupElement.p1p1(curve, ZERO, ONE, ONE, ONE); assertThat(t.curve, is(equalTo(curve))); assertThat(t.repr, is(GroupElement.Representation.P1P1)); assertThat(t.X, is(ZERO)); assertThat(t.Y, is(ONE)); assertThat(t.Z, is(ONE)); assertThat(t.T, is(ONE)); }
// This test is slow (~6s) due to math utils using an inferior algorithm to calculate the result. @Test public void doubleScalarMultiplyVariableTimeReturnsExpectedResult() { for (int i = 0; i < 50; i++) { // Arrange: final GroupElement basePoint = ed25519.getB(); final GroupElement g = MathUtils.getRandomGroupElement(); g.precompute(false); final FieldElement f1 = MathUtils.getRandomFieldElement(); final FieldElement f2 = MathUtils.getRandomFieldElement(); // Act: final GroupElement h1 = basePoint.doubleScalarMultiplyVariableTime(g, f2.toByteArray(), f1.toByteArray()); final GroupElement h2 = MathUtils.doubleScalarMultiplyGroupElements(basePoint, f1, g, f2); // Assert: Assert.assertThat(h1, IsEqual.equalTo(h2)); } }
private int getSpecifity(final GroupElement ce) { int specificity = 0; for (final RuleConditionElement object : ce.getChildren()) { if (object instanceof Pattern) { specificity += getSpecifity((Pattern) object); } else if (object instanceof GroupElement) { specificity += getSpecifity((GroupElement) object); } } return specificity; }
/** Test method for {@link GroupElement#toRadix16(byte[])}. */ @Test public void testToRadix16() { assertThat(GroupElement.toRadix16(BYTES_ZERO), is(RADIX16_ZERO)); assertThat(GroupElement.toRadix16(BYTES_ONE), is(RADIX16_ONE)); assertThat(GroupElement.toRadix16(BYTES_42), is(RADIX16_42)); byte[] from1234567890 = GroupElement.toRadix16(BYTES_1234567890); int total = 0; for (int i = 0; i < from1234567890.length; i++) { assertThat(from1234567890[i], is(greaterThanOrEqualTo((byte) -8))); assertThat(from1234567890[i], is(lessThanOrEqualTo((byte) 8))); total += from1234567890[i] * Math.pow(16, i); } assertThat(total, is(1234567890)); byte[] pkrR16 = GroupElement.toRadix16(BYTES_PKR); for (int i = 0; i < pkrR16.length; i++) { assertThat(pkrR16[i], is(greaterThanOrEqualTo((byte) -8))); assertThat(pkrR16[i], is(lessThanOrEqualTo((byte) 8))); } }
/** * Test method for {@link GroupElement#toByteArray()}. TODO 20141001 BR: why test with points * which are not on the curve? */ @Test public void testToByteArray() { byte[] zerozero = GroupElement.p2(curve, ZERO, ZERO, ONE).toByteArray(); assertThat(zerozero.length, is(equalTo(BYTES_ZEROZERO.length))); assertThat(zerozero, is(equalTo(BYTES_ZEROZERO))); byte[] oneone = GroupElement.p2(curve, ONE, ONE, ONE).toByteArray(); assertThat(oneone.length, is(equalTo(BYTES_ONEONE.length))); assertThat(oneone, is(equalTo(BYTES_ONEONE))); byte[] tenzero = GroupElement.p2(curve, TEN, ZERO, ONE).toByteArray(); assertThat(tenzero.length, is(equalTo(BYTES_TENZERO.length))); assertThat(tenzero, is(equalTo(BYTES_TENZERO))); byte[] oneten = GroupElement.p2(curve, ONE, TEN, ONE).toByteArray(); assertThat(oneten.length, is(equalTo(BYTES_ONETEN.length))); assertThat(oneten, is(equalTo(BYTES_ONETEN))); byte[] pkr = GroupElement.p2(curve, PKR[0], PKR[1], ONE).toByteArray(); assertThat(pkr.length, is(equalTo(BYTES_PKR.length))); assertThat(pkr, is(equalTo(BYTES_PKR))); }
@Test public void isOnCurveReturnsFalseForPointsNotOnTheCurve() { for (int i = 0; i < 100; i++) { // Arrange: final GroupElement g = MathUtils.getRandomGroupElement(); final GroupElement h = GroupElement.p2(curve, g.getX(), g.getY(), g.getZ().multiply(curve.getField().TWO)); // Assert (can only fail for 5*Z^2=1): Assert.assertThat(h.isOnCurve(), IsEqual.equalTo(false)); } }
private GroupElement[] processNamedConsequences(GroupElement[] ands) { List<GroupElement> result = new ArrayList<GroupElement>(); for (GroupElement and : ands) { List<RuleConditionElement> children = and.getChildren(); for (int i = 0; i < children.size(); i++) { RuleConditionElement child = children.get(i); if (child instanceof NamedConsequence) { GroupElement clonedAnd = GroupElementFactory.newAndInstance(); for (int j = 0; j < i; j++) { clonedAnd.addChild(children.get(j).clone()); } ((NamedConsequence) child).setTerminal(true); clonedAnd.addChild(child); children.remove(i--); result.add(clonedAnd); } } result.add(and); } return result.toArray(new GroupElement[result.size()]); }