EdDSA: Reduce diff between vendored code and upstream

Includes missing license information.
This commit is contained in:
str4d
2019-08-10 15:39:41 +00:00
parent 08be6a4f4a
commit 13190931b9
45 changed files with 1008 additions and 415 deletions

View File

@ -1,3 +1,14 @@
/**
* EdDSA-Java by str4d
*
* To the extent possible under law, the person who associated CC0 with
* EdDSA-Java has waived all copyright and related or neighboring rights
* to EdDSA-Java.
*
* You should have received a copy of the CC0 legalcode along with this
* work. If not, see <https://creativecommons.org/publicdomain/zero/1.0/>.
*
*/
package net.i2p.crypto.eddsa;
import java.io.ByteArrayOutputStream;
@ -153,7 +164,7 @@ public class EdDSAEngine extends Signature {
}
} else if (!key.getParams().getHashAlgorithm().equals(digest.getAlgorithm()))
throw new InvalidKeyException("Key hash algorithm does not match chosen digest");
} else if (publicKey.getClass().getName().equals("sun.security.x509.X509Key")) {
} else if (publicKey.getFormat().equals("X.509")) {
// X509Certificate will sometimes contain an X509Key rather than the EdDSAPublicKey itself; the contained
// key is valid but needs to be instanced as an EdDSAPublicKey before it can be used.
EdDSAPublicKey parsedPublicKey;

View File

@ -1,3 +1,14 @@
/**
* EdDSA-Java by str4d
*
* To the extent possible under law, the person who associated CC0 with
* EdDSA-Java has waived all copyright and related or neighboring rights
* to EdDSA-Java.
*
* You should have received a copy of the CC0 legalcode along with this
* work. If not, see <https://creativecommons.org/publicdomain/zero/1.0/>.
*
*/
package net.i2p.crypto.eddsa;
import net.i2p.crypto.eddsa.spec.EdDSAParameterSpec;
@ -7,18 +18,17 @@ import net.i2p.crypto.eddsa.spec.EdDSAParameterSpec;
*
* @since 0.9.15
* @author str4d
*
*/
public interface EdDSAKey {
/**
* The reported key algorithm for all EdDSA keys
* @since 0.9.36
*/
public String KEY_ALGORITHM = "EdDSA";
String KEY_ALGORITHM = "EdDSA";
/**
* @return a parameter specification representing the EdDSA domain
* parameters for the key.
*/
public EdDSAParameterSpec getParams();
EdDSAParameterSpec getParams();
}

View File

@ -1,3 +1,14 @@
/**
* EdDSA-Java by str4d
*
* To the extent possible under law, the person who associated CC0 with
* EdDSA-Java has waived all copyright and related or neighboring rights
* to EdDSA-Java.
*
* You should have received a copy of the CC0 legalcode along with this
* work. If not, see <https://creativecommons.org/publicdomain/zero/1.0/>.
*
*/
package net.i2p.crypto.eddsa;
import java.security.PrivateKey;
@ -12,21 +23,16 @@ import net.i2p.crypto.eddsa.spec.EdDSAPrivateKeySpec;
/**
* An EdDSA private key.
*<p>
* Warning: Private key encoding is based on the current curdle WG draft,
* and is subject to change. See getEncoded().
*</p><p>
* For compatibility with older releases, decoding supports both the old and new
* draft specifications. See decode().
*</p><p>
* Ref: https://tools.ietf.org/html/draft-ietf-curdle-pkix-04
*</p><p>
* Old Ref: https://tools.ietf.org/html/draft-josefsson-pkix-eddsa-04
*</p>
* <p>
* For compatibility with older releases, decoding supports both RFC 8410 and an
* older draft specifications.
*
* @since 0.9.15
* @author str4d
*
* @see <a href="https://tools.ietf.org/html/rfc8410">RFC 8410</a>
* @see <a href=
* "https://tools.ietf.org/html/draft-josefsson-pkix-eddsa-04">Older draft
* specification</a>
*/
public class EdDSAPrivateKey implements EdDSAKey, PrivateKey {
private static final long serialVersionUID = 23495873459878957L;
@ -72,62 +78,62 @@ public class EdDSAPrivateKey implements EdDSAKey, PrivateKey {
/**
* Returns the private key in its canonical encoding.
*<p>
* <p>
* This implements the following specs:
*<ul><li>
* General encoding: https://tools.ietf.org/html/draft-ietf-curdle-pkix-04
*</li><li>
* Key encoding: https://tools.ietf.org/html/rfc8032
*</li></ul>
*<p>
* This encodes the seed. It will return null if constructed from
* a spec which was directly constructed from H, in which case seed is null.
*</p><p>
* <ul>
* <li>General encoding: https://tools.ietf.org/html/rfc8410</li>
* <li>Key encoding: https://tools.ietf.org/html/rfc8032</li>
* </ul>
* <p>
* This encodes the seed. It will return null if constructed from a spec which
* was directly constructed from H, in which case seed is null.
* <p>
* For keys in older formats, decoding and then re-encoding is sufficient to
* migrate them to the canonical encoding.
*</p>
* <p>
* Relevant spec quotes:
*<pre>
*
* <pre>
* OneAsymmetricKey ::= SEQUENCE {
* version Version,
* privateKeyAlgorithm PrivateKeyAlgorithmIdentifier,
* privateKey PrivateKey,
* attributes [0] Attributes OPTIONAL,
* attributes [0] IMPLICIT Attributes OPTIONAL,
* ...,
* [[2: publicKey [1] PublicKey OPTIONAL ]],
* [[2: publicKey [1] IMPLICIT PublicKey OPTIONAL ]],
* ...
* }
*
* Version ::= INTEGER
* PrivateKeyAlgorithmIdentifier ::= AlgorithmIdentifier
* PrivateKey ::= OCTET STRING
* PublicKey ::= OCTET STRING
* PublicKey ::= BIT STRING
* Attributes ::= SET OF Attribute
*</pre>
* </pre>
*
*<pre>
* <pre>
* ... when encoding a OneAsymmetricKey object, the private key is wrapped
* in a CurvePrivateKey object and wrapped by the OCTET STRING of the
* 'privateKey' field.
* "privateKey" field.
*
* CurvePrivateKey ::= OCTET STRING
*</pre>
* </pre>
*
*<pre>
* <pre>
* AlgorithmIdentifier ::= SEQUENCE {
* algorithm OBJECT IDENTIFIER,
* parameters ANY DEFINED BY algorithm OPTIONAL
* }
*
* For all of the OIDs, the parameters MUST be absent.
*</pre>
* </pre>
*
*<pre>
* <pre>
* id-Ed25519 OBJECT IDENTIFIER ::= { 1 3 101 112 }
*</pre>
* </pre>
*
* @return 48 bytes for Ed25519, null for other curves
* @since implemented in 0.9.25
* @return 48 bytes for Ed25519, null for other curves
* @since implemented in 0.9.25
*/
@Override
public byte[] getEncoded() {
@ -171,22 +177,20 @@ public class EdDSAPrivateKey implements EdDSAKey, PrivateKey {
/**
* Extracts the private key bytes from the provided encoding.
*<p>
* This will decode data conforming to the current spec at
* https://tools.ietf.org/html/draft-ietf-curdle-pkix-04
* or as inferred from the old spec at
* https://tools.ietf.org/html/draft-josefsson-pkix-eddsa-04.
*</p><p>
* Contrary to draft-ietf-curdle-pkix-04, it WILL accept a parameter value
* of NULL, as it is required for interoperability with the default Java
* keystore. Other implementations MUST NOT copy this behaviour from here
* unless they also need to read keys from the default Java keystore.
*</p><p>
* <p>
* This will decode data conforming to RFC 8410 or as inferred from the older
* draft spec at https://tools.ietf.org/html/draft-josefsson-pkix-eddsa-04.
* <p>
* Per RFC 8410 section 3, this function WILL accept a parameter value of
* NULL, as it is required for interoperability with the default Java keystore.
* Other implementations MUST NOT copy this behaviour from here unless they also
* need to read keys from the default Java keystore.
* <p>
* This is really dumb for now. It does not use a general-purpose ASN.1 decoder.
* See also getEncoded().
*
* @return 32 bytes for Ed25519, throws for other curves
* @since 0.9.25
* @return 32 bytes for Ed25519, throws for other curves
* @since 0.9.25
*/
private static byte[] decode(byte[] d) throws InvalidKeySpecException {
try {
@ -244,13 +248,18 @@ public class EdDSAPrivateKey implements EdDSAKey, PrivateKey {
} else {
// Handle parameter value of NULL
//
// Quote https://tools.ietf.org/html/draft-ietf-curdle-pkix-04 :
// For all of the OIDs, the parameters MUST be absent.
// Regardless of the defect in the original 1997 syntax,
// implementations MUST NOT accept a parameters value of NULL.
// Quoting RFC 8410 section 3:
// > For all of the OIDs, the parameters MUST be absent.
// >
// > It is possible to find systems that require the parameters to be
// > present. This can be due to either a defect in the original 1997
// > syntax or a programming error where developers never got input where
// > this was not true. The optimal solution is to fix these systems;
// > where this is not possible, the problem needs to be restricted to
// > that subsystem and not propagated to the Internet.
//
// But Java's default keystore puts it in (when decoding as
// PKCS8 and then re-encoding to pass on), so we must accept it.
// Java's default keystore puts it in (when decoding as PKCS8 and then
// re-encoding to pass on), so we must accept it.
if (idlen == 7) {
if (d[idx++] != 0x05 ||
d[idx++] != 0) {
@ -281,36 +290,36 @@ public class EdDSAPrivateKey implements EdDSAKey, PrivateKey {
}
/**
* @return will be null if constructed from a spec which was
* directly constructed from H
* @return will be null if constructed from a spec which was directly
* constructed from H
*/
public byte[] getSeed() {
return seed;
}
/**
* @return the hash of the seed
* @return the hash of the seed
*/
public byte[] getH() {
return h;
}
/**
* @return the private key
* @return the private key
*/
public byte[] geta() {
return a;
}
/**
* @return the public key
* @return the public key
*/
public GroupElement getA() {
return A;
}
/**
* @return the public key
* @return the public key
*/
public byte[] getAbyte() {
return Abyte;

View File

@ -1,3 +1,14 @@
/**
* EdDSA-Java by str4d
*
* To the extent possible under law, the person who associated CC0 with
* EdDSA-Java has waived all copyright and related or neighboring rights
* to EdDSA-Java.
*
* You should have received a copy of the CC0 legalcode along with this
* work. If not, see <https://creativecommons.org/publicdomain/zero/1.0/>.
*
*/
package net.i2p.crypto.eddsa;
import java.security.PublicKey;
@ -12,26 +23,21 @@ import net.i2p.crypto.eddsa.spec.EdDSAPublicKeySpec;
/**
* An EdDSA public key.
*<p>
* Warning: Public key encoding is is based on the current curdle WG draft,
* and is subject to change. See getEncoded().
*</p><p>
* For compatibility with older releases, decoding supports both the old and new
* draft specifications. See decode().
*</p><p>
* Ref: https://tools.ietf.org/html/draft-ietf-curdle-pkix-04
*</p><p>
* Old Ref: https://tools.ietf.org/html/draft-josefsson-pkix-eddsa-04
*</p>
* <p>
* For compatibility with older releases, decoding supports both RFC 8410 and an
* older draft specification.
*
* @since 0.9.15
* @author str4d
*
* @see <a href="https://tools.ietf.org/html/rfc8410">RFC 8410</a>
* @see <a href=
* "https://tools.ietf.org/html/draft-josefsson-pkix-eddsa-04">Older draft
* specification</a>
*/
public class EdDSAPublicKey implements EdDSAKey, PublicKey {
private static final long serialVersionUID = 9837459837498475L;
private final GroupElement A;
private GroupElement Aneg;
private GroupElement Aneg = null;
private final byte[] Abyte;
private final EdDSAParameterSpec edDsaSpec;
@ -67,19 +73,19 @@ public class EdDSAPublicKey implements EdDSAKey, PublicKey {
/**
* Returns the public key in its canonical encoding.
*<p>
* <p>
* This implements the following specs:
*<ul><li>
* General encoding: https://tools.ietf.org/html/draft-ietf-curdle-pkix-04
*</li><li>
* Key encoding: https://tools.ietf.org/html/rfc8032
*</li></ul>
*<p>
* <ul>
* <li>General encoding: https://tools.ietf.org/html/rfc8410</li>
* <li>Key encoding: https://tools.ietf.org/html/rfc8032</li>
* </ul>
* <p>
* For keys in older formats, decoding and then re-encoding is sufficient to
* migrate them to the canonical encoding.
*</p>
* <p>
* Relevant spec quotes:
*<pre>
*
* <pre>
* In the X.509 certificate, the subjectPublicKeyInfo field has the
* SubjectPublicKeyInfo type, which has the following ASN.1 syntax:
*
@ -87,23 +93,23 @@ public class EdDSAPublicKey implements EdDSAKey, PublicKey {
* algorithm AlgorithmIdentifier,
* subjectPublicKey BIT STRING
* }
*</pre>
* </pre>
*
*<pre>
* <pre>
* AlgorithmIdentifier ::= SEQUENCE {
* algorithm OBJECT IDENTIFIER,
* parameters ANY DEFINED BY algorithm OPTIONAL
* }
*
* For all of the OIDs, the parameters MUST be absent.
*</pre>
* </pre>
*
*<pre>
* <pre>
* id-Ed25519 OBJECT IDENTIFIER ::= { 1 3 101 112 }
*</pre>
* </pre>
*
* @return 44 bytes for Ed25519, null for other curves
* @since implemented in 0.9.25
* @return 44 bytes for Ed25519, null for other curves
* @since implemented in 0.9.25
*/
@Override
public byte[] getEncoded() {
@ -137,23 +143,20 @@ public class EdDSAPublicKey implements EdDSAKey, PublicKey {
/**
* Extracts the public key bytes from the provided encoding.
*<p>
* This will decode data conforming to the current spec at
* https://tools.ietf.org/html/draft-ietf-curdle-pkix-04
* or the old spec at
* <p>
* This will decode data conforming to RFC 8410 or the older draft spec at
* https://tools.ietf.org/html/draft-josefsson-pkix-eddsa-04.
*</p><p>
* Contrary to draft-ietf-curdle-pkix-04, it WILL accept a parameter value
* of NULL, as it is required for interoperability with the default Java
* keystore. Other implementations MUST NOT copy this behaviour from here
* unless they also need to read keys from the default Java keystore.
*</p><p>
* <p>
* Per RFC 8410 section 3, this function WILL accept a parameter value of
* NULL, as it is required for interoperability with the default Java keystore.
* Other implementations MUST NOT copy this behaviour from here unless they also
* need to read keys from the default Java keystore.
* <p>
* This is really dumb for now. It does not use a general-purpose ASN.1 decoder.
* See also getEncoded().
*</p>
*
* @return 32 bytes for Ed25519, throws for other curves
* @since 0.9.25
* @return 32 bytes for Ed25519, throws for other curves
* @since 0.9.25
*/
private static byte[] decode(byte[] d) throws InvalidKeySpecException {
try {
@ -208,13 +211,18 @@ public class EdDSAPublicKey implements EdDSAKey, PublicKey {
} else {
// Handle parameter value of NULL
//
// Quote https://tools.ietf.org/html/draft-ietf-curdle-pkix-04 :
// For all of the OIDs, the parameters MUST be absent.
// Regardless of the defect in the original 1997 syntax,
// implementations MUST NOT accept a parameters value of NULL.
// Quoting RFC 8410 section 3:
// > For all of the OIDs, the parameters MUST be absent.
// >
// > It is possible to find systems that require the parameters to be
// > present. This can be due to either a defect in the original 1997
// > syntax or a programming error where developers never got input where
// > this was not true. The optimal solution is to fix these systems;
// > where this is not possible, the problem needs to be restricted to
// > that subsystem and not propagated to the Internet.
//
// But Java's default keystore puts it in (when decoding as
// PKCS8 and then re-encoding to pass on), so we must accept it.
// Java's default keystore puts it in (when decoding as PKCS8 and then
// re-encoding to pass on), so we must accept it.
if (idlen == 7) {
if (d[idx++] != 0x05 ||
d[idx++] != 0) {
@ -245,7 +253,8 @@ public class EdDSAPublicKey implements EdDSAKey, PublicKey {
}
public GroupElement getNegativeA() {
// Only read Aneg once, otherwise read re-ordering might occur between here and return. Requires all GroupElement's fields to be final.
// Only read Aneg once, otherwise read re-ordering might occur between
// here and return. Requires all GroupElement's fields to be final.
GroupElement ourAneg = Aneg;
if(ourAneg == null) {
ourAneg = A.negate();

View File

@ -1,3 +1,14 @@
/**
* EdDSA-Java by str4d
*
* To the extent possible under law, the person who associated CC0 with
* EdDSA-Java has waived all copyright and related or neighboring rights
* to EdDSA-Java.
*
* You should have received a copy of the CC0 legalcode along with this
* work. If not, see <https://creativecommons.org/publicdomain/zero/1.0/>.
*
*/
package net.i2p.crypto.eddsa;
import java.security.InvalidKeyException;

View File

@ -1,3 +1,14 @@
/**
* EdDSA-Java by str4d
*
* To the extent possible under law, the person who associated CC0 with
* EdDSA-Java has waived all copyright and related or neighboring rights
* to EdDSA-Java.
*
* You should have received a copy of the CC0 legalcode along with this
* work. If not, see <https://creativecommons.org/publicdomain/zero/1.0/>.
*
*/
package net.i2p.crypto.eddsa;
import java.security.InvalidAlgorithmParameterException;
@ -32,7 +43,7 @@ public class KeyPairGenerator extends KeyPairGeneratorSpi {
static {
edParameters = new Hashtable<Integer, AlgorithmParameterSpec>();
edParameters.put(Integer.valueOf(DEFAULT_KEYSIZE), new EdDSAGenParameterSpec(EdDSANamedCurveTable.ED_25519));
edParameters.put(Integer.valueOf(256), new EdDSAGenParameterSpec(EdDSANamedCurveTable.ED_25519));
}
public void initialize(int keysize, SecureRandom random) {

View File

@ -1,3 +1,14 @@
/**
* EdDSA-Java by str4d
*
* To the extent possible under law, the person who associated CC0 with
* EdDSA-Java has waived all copyright and related or neighboring rights
* to EdDSA-Java.
*
* You should have received a copy of the CC0 legalcode along with this
* work. If not, see <https://creativecommons.org/publicdomain/zero/1.0/>.
*
*/
package net.i2p.crypto.eddsa;
/**
@ -65,6 +76,9 @@ public class Utils {
*/
public static byte[] hexToBytes(String s) {
int len = s.length();
if (len % 2 != 0) {
throw new IllegalArgumentException("Hex string must have an even 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)

View File

@ -1,3 +1,14 @@
/**
* EdDSA-Java by str4d
*
* To the extent possible under law, the person who associated CC0 with
* EdDSA-Java has waived all copyright and related or neighboring rights
* to EdDSA-Java.
*
* You should have received a copy of the CC0 legalcode along with this
* work. If not, see <https://creativecommons.org/publicdomain/zero/1.0/>.
*
*/
package net.i2p.crypto.eddsa.math;
import net.i2p.crypto.eddsa.Utils;

View File

@ -1,10 +1,21 @@
/**
* EdDSA-Java by str4d
*
* To the extent possible under law, the person who associated CC0 with
* EdDSA-Java has waived all copyright and related or neighboring rights
* to EdDSA-Java.
*
* You should have received a copy of the CC0 legalcode along with this
* work. If not, see <https://creativecommons.org/publicdomain/zero/1.0/>.
*
*/
package net.i2p.crypto.eddsa.math;
import java.io.Serializable;
/**
* A twisted Edwards curve.
* Points on the curve satisfy -x^2 + y^2 = 1 + d x^2y^2
* Points on the curve satisfy $-x^2 + y^2 = 1 + d x^2y^2$
*
* @since 0.9.15
* @author str4d

View File

@ -1,9 +1,20 @@
/**
* EdDSA-Java by str4d
*
* To the extent possible under law, the person who associated CC0 with
* EdDSA-Java has waived all copyright and related or neighboring rights
* to EdDSA-Java.
*
* You should have received a copy of the CC0 legalcode along with this
* work. If not, see <https://creativecommons.org/publicdomain/zero/1.0/>.
*
*/
package net.i2p.crypto.eddsa.math;
import java.io.Serializable;
/**
* Common interface for all (b-1)-bit encodings of elements
* Common interface for all $(b-1)$-bit encodings of elements
* of EdDSA finite fields.
*
* @since 0.9.15
@ -20,25 +31,27 @@ public abstract class Encoding implements Serializable {
}
/**
* Encode a FieldElement in its (b-1)-bit encoding.
* @return the (b-1)-bit encoding of this FieldElement.
* Encode a FieldElement in its $(b-1)$-bit encoding.
* @param x the FieldElement to encode
* @return the $(b-1)$-bit encoding of this FieldElement.
*/
public abstract byte[] encode(FieldElement x);
/**
* Decode a FieldElement from its (b-1)-bit encoding.
* Decode a FieldElement from its $(b-1)$-bit encoding.
* The highest bit is masked out.
* @param in the (b-1)-bit encoding of a FieldElement.
* @param in the $(b-1)$-bit encoding of a FieldElement.
* @return the FieldElement represented by 'val'.
*/
public abstract FieldElement decode(byte[] in);
/**
* From the Ed25519 paper:<br>
* x is negative if the (b-1)-bit encoding of x is lexicographically larger
* than the (b-1)-bit encoding of -x. If q is an odd prime and the encoding
* is the little-endian representation of {0, 1,..., q-1} then the negative
* elements of F_q are {1, 3, 5,..., q-2}.
* $x$ is negative if the $(b-1)$-bit encoding of $x$ is lexicographically larger
* than the $(b-1)$-bit encoding of -x. If $q$ is an odd prime and the encoding
* is the little-endian representation of $\{0, 1,\dots, q-1\}$ then the negative
* elements of $F_q$ are $\{1, 3, 5,\dots, q-2\}$.
* @param x the FieldElement to check
* @return true if negative
*/
public abstract boolean isNegative(FieldElement x);

View File

@ -1,3 +1,14 @@
/**
* EdDSA-Java by str4d
*
* To the extent possible under law, the person who associated CC0 with
* EdDSA-Java has waived all copyright and related or neighboring rights
* to EdDSA-Java.
*
* You should have received a copy of the CC0 legalcode along with this
* work. If not, see <https://creativecommons.org/publicdomain/zero/1.0/>.
*
*/
package net.i2p.crypto.eddsa.math;
import java.io.Serializable;

View File

@ -1,13 +1,22 @@
/**
* EdDSA-Java by str4d
*
* To the extent possible under law, the person who associated CC0 with
* EdDSA-Java has waived all copyright and related or neighboring rights
* to EdDSA-Java.
*
* You should have received a copy of the CC0 legalcode along with this
* work. If not, see <https://creativecommons.org/publicdomain/zero/1.0/>.
*
*/
package net.i2p.crypto.eddsa.math;
import java.io.Serializable;
/**
*
* Note: concrete subclasses must implement hashCode() and equals()
*
* @since 0.9.15
*
*/
public abstract class FieldElement implements Serializable {
private static final long serialVersionUID = 1239527465875676L;
@ -22,8 +31,8 @@ public abstract class FieldElement implements Serializable {
}
/**
* Encode a FieldElement in its (b-1)-bit encoding.
* @return the (b-1)-bit encoding of this FieldElement.
* Encode a FieldElement in its $(b-1)$-bit encoding.
* @return the $(b-1)$-bit encoding of this FieldElement.
*/
public byte[] toByteArray() {
return f.getEncoding().encode(this);

View File

@ -1,3 +1,14 @@
/**
* EdDSA-Java by str4d
*
* To the extent possible under law, the person who associated CC0 with
* EdDSA-Java has waived all copyright and related or neighboring rights
* to EdDSA-Java.
*
* You should have received a copy of the CC0 legalcode along with this
* work. If not, see <https://creativecommons.org/publicdomain/zero/1.0/>.
*
*/
package net.i2p.crypto.eddsa.math;
import net.i2p.crypto.eddsa.Utils;
@ -6,7 +17,7 @@ import java.io.Serializable;
import java.util.Arrays;
/**
* A point (x,y) on an EdDSA curve.
* A point $(x,y)$ on an EdDSA curve.
* <p>
* Reviewed/commented by Bloody Rookie (nemproject@gmx.de)
* <p>
@ -20,36 +31,36 @@ import java.util.Arrays;
*
* @since 0.9.15
* @author str4d
*
*/
public class GroupElement implements Serializable {
private static final long serialVersionUID = 2395879087349587L;
/**
* Available representations for a group element.
* <p><ul>
* <li>P2: Projective representation (X:Y:Z) satisfying x=X/Z, y=Y/Z.
* <li>P3: Extended projective representation (X:Y:Z:T) satisfying x=X/Z, y=Y/Z, XY=ZT.
* <li>P1P1: Completed representation ((X:Z), (Y:T)) satisfying x=X/Z, y=Y/T.
* <li>PRECOMP: Precomputed representation (y+x, y-x, 2dxy).
* <li>CACHED: Cached representation (Y+X, Y-X, Z, 2dT)
* <ul>
* <li>P2: Projective representation $(X:Y:Z)$ satisfying $x=X/Z, y=Y/Z$.
* <li>P3: Extended projective representation $(X:Y:Z:T)$ satisfying $x=X/Z, y=Y/Z, XY=ZT$.
* <li>P3PrecomputedDouble: P3 but with dblPrecmp populated.
* <li>P1P1: Completed representation $((X:Z), (Y:T))$ satisfying $x=X/Z, y=Y/T$.
* <li>PRECOMP: Precomputed representation $(y+x, y-x, 2dxy)$.
* <li>CACHED: Cached representation $(Y+X, Y-X, Z, 2dT)$
* </ul>
*/
public enum Representation {
/** Projective (P^2): (X:Y:Z) satisfying x=X/Z, y=Y/Z */
/** Projective ($P^2$): $(X:Y:Z)$ satisfying $x=X/Z, y=Y/Z$ */
P2,
/** Extended (P^3): (X:Y:Z:T) satisfying x=X/Z, y=Y/Z, XY=ZT */
/** Extended ($P^3$): $(X:Y:Z:T)$ satisfying $x=X/Z, y=Y/Z, XY=ZT$ */
P3,
/**
* Can only be requested. Results in P3 representation but also populates dblPrecmp.
* @since 0.9.36
*/
P3PrecomputedDouble,
/** Completed (P x P): ((X:Z),(Y:T)) satisfying x=X/Z, y=Y/T */
/** Completed ($P \times P$): $((X:Z),(Y:T))$ satisfying $x=X/Z, y=Y/T$ */
P1P1,
/** Precomputed (Duif): (y+x,y-x,2dxy) */
/** Precomputed (Duif): $(y+x,y-x,2dxy)$ */
PRECOMP,
/** Cached: (Y+X,Y-X,Z,2dT) */
/** Cached: $(Y+X,Y-X,Z,2dT)$ */
CACHED
}
@ -57,9 +68,9 @@ public class GroupElement implements Serializable {
* Creates a new group element in P2 representation.
*
* @param curve The curve.
* @param X The X coordinate.
* @param Y The Y coordinate.
* @param Z The Z coordinate.
* @param X The $X$ coordinate.
* @param Y The $Y$ coordinate.
* @param Z The $Z$ coordinate.
* @return The group element in P2 representation.
*/
public static GroupElement p2(
@ -71,13 +82,13 @@ public class GroupElement implements Serializable {
}
/**
* Creates a new group element in P3 representation.
* Creates a new group element in P3 representation, without pre-computation.
*
* @param curve The curve.
* @param X The X coordinate.
* @param Y The Y coordinate.
* @param Z The Z coordinate.
* @param T The T coordinate.
* @param X The $X$ coordinate.
* @param Y The $Y$ coordinate.
* @param Z The $Z$ coordinate.
* @param T The $T$ coordinate.
* @return The group element in P3 representation.
*/
public static GroupElement p3(
@ -93,10 +104,10 @@ public class GroupElement implements Serializable {
* Creates a new group element in P3 representation, potentially with pre-computation.
*
* @param curve The curve.
* @param X The X coordinate.
* @param Y The Y coordinate.
* @param Z The Z coordinate.
* @param T The T coordinate.
* @param X The $X$ coordinate.
* @param Y The $Y$ coordinate.
* @param Z The $Z$ coordinate.
* @param T The $T$ coordinate.
* @param precomputeDoubleOnly If true, populate dblPrecmp, else set to null.
* @return The group element in P3 representation.
* @since 0.9.36
@ -115,10 +126,10 @@ public class GroupElement implements Serializable {
* Creates a new group element in P1P1 representation.
*
* @param curve The curve.
* @param X The X coordinate.
* @param Y The Y coordinate.
* @param Z The Z coordinate.
* @param T The T coordinate.
* @param X The $X$ coordinate.
* @param Y The $Y$ coordinate.
* @param Z The $Z$ coordinate.
* @param T The $T$ coordinate.
* @return The group element in P1P1 representation.
*/
public static GroupElement p1p1(
@ -134,9 +145,9 @@ public class GroupElement implements Serializable {
* Creates a new group element in PRECOMP representation.
*
* @param curve The curve.
* @param ypx The y + x value.
* @param ymx The y - x value.
* @param xy2d The 2 * d * x * y value.
* @param ypx The $y + x$ value.
* @param ymx The $y - x$ value.
* @param xy2d The $2 * d * x * y$ value.
* @return The group element in PRECOMP representation.
*/
public static GroupElement precomp(
@ -151,10 +162,10 @@ public class GroupElement implements Serializable {
* Creates a new group element in CACHED representation.
*
* @param curve The curve.
* @param YpX The Y + X value.
* @param YmX The Y - X value.
* @param Z The Z coordinate.
* @param T2d The 2 * d * T value.
* @param YpX The $Y + X$ value.
* @param YmX The $Y - X$ value.
* @param Z The $Z$ coordinate.
* @param T2d The $2 * d * T$ value.
* @return The group element in CACHED representation.
*/
public static GroupElement cached(
@ -217,10 +228,10 @@ public class GroupElement implements Serializable {
*
* @param curve The curve.
* @param repr The representation used to represent the group element.
* @param X The X coordinate.
* @param Y The Y coordinate.
* @param Z The Z coordinate.
* @param T The T coordinate.
* @param X The $X$ coordinate.
* @param Y The $Y$ coordinate.
* @param Z The $Z$ coordinate.
* @param T The $T$ coordinate.
*/
public GroupElement(
final Curve curve,
@ -237,10 +248,10 @@ public class GroupElement implements Serializable {
*
* @param curve The curve.
* @param repr The representation used to represent the group element.
* @param X The X coordinate.
* @param Y The Y coordinate.
* @param Z The Z coordinate.
* @param T The T coordinate.
* @param X The $X$ coordinate.
* @param Y The $Y$ coordinate.
* @param Z The $Z$ coordinate.
* @param T The $T$ coordinate.
* @param precomputeDouble If true, populate dblPrecmp, else set to null.
* @since 0.9.36
*/
@ -263,16 +274,16 @@ public class GroupElement implements Serializable {
}
/**
* Creates a group element for a curve from a given encoded point.
* Creates a group element for a curve from a given encoded point. No pre-computation.
* <p>
* A point (x,y) is encoded by storing y in bit 0 to bit 254 and the sign of x in bit 255.
* x is recovered in the following way:
* A point $(x,y)$ is encoded by storing $y$ in bit 0 to bit 254 and the sign of $x$ in bit 255.
* $x$ is recovered in the following way:
* </p><ul>
* <li>x = sign(x) * sqrt((y^2 - 1) / (d * y^2 + 1)) = sign(x) * sqrt(u / v) with u = y^2 - 1 and v = d * y^2 + 1.
* <li>Setting = (u * v^3) * (u * v^7)^((q - 5) / 8) one has ^2 = +-(u / v).
* <li>If v * = -u multiply with i=sqrt(-1).
* <li>Set x := .
* <li>If sign(x) != bit 255 of s then negate x.
* <li>$x = sign(x) * \sqrt{(y^2 - 1) / (d * y^2 + 1)} = sign(x) * \sqrt{u / v}$ with $u = y^2 - 1$ and $v = d * y^2 + 1$.
* <li>Setting = (u * v^3) * (u * v^7)^{((q - 5) / 8)}$ one has ^2 = \pm(u / v)$.
* <li>If $v * β = -u$ multiply $β$ with $i=\sqrt{-1}$.
* <li>Set $x := β$.
* <li>If $sign(x) \ne$ bit 255 of $s$ then negate $x$.
* </ul>
*
* @param curve The curve.
@ -285,14 +296,14 @@ public class GroupElement implements Serializable {
/**
* Creates a group element for a curve from a given encoded point. With optional pre-computation.
* <p>
* A point (x,y) is encoded by storing y in bit 0 to bit 254 and the sign of x in bit 255.
* x is recovered in the following way:
* A point $(x,y)$ is encoded by storing $y$ in bit 0 to bit 254 and the sign of $x$ in bit 255.
* $x$ is recovered in the following way:
* </p><ul>
* <li>x = sign(x) * \sqrt{(y^2 - 1) / (d * y^2 + 1)} = sign(x) * \sqrt{u / v} with u = y^2 - 1 and v = d * y^2 + 1.
* <li>Setting β = (u * v^3) * (u * v^7)^((q - 5) / 8) one has β^2 = +-(u / v).
* <li>If v * β = -u multiply β with i=sqrt(-1).
* <li>Set x := β.
* <li>If sign(x) != bit 255 of s then negate x.
* <li>$x = sign(x) * \sqrt{(y^2 - 1) / (d * y^2 + 1)} = sign(x) * \sqrt{u / v}$ with $u = y^2 - 1$ and $v = d * y^2 + 1$.
* <li>Setting $β = (u * v^3) * (u * v^7)^{((q - 5) / 8)}$ one has $β^2 = \pm(u / v)$.
* <li>If $v * β = -u$ multiply $β$ with $i=\sqrt{-1}$.
* <li>Set $x := β$.
* <li>If $sign(x) \ne$ bit 255 of $s$ then negate $x$.
* </ul>
*
* @param curve The curve.
@ -305,7 +316,7 @@ public class GroupElement implements Serializable {
y = curve.getField().fromByteArray(s);
yy = y.square();
// u = y^2-1
// u = y^2-1
u = yy.subtractOne();
// v = dy^2+1
@ -371,40 +382,40 @@ public class GroupElement implements Serializable {
}
/**
* Gets the X value of the group element.
* This is for most representation the projective X coordinate.
* Gets the $X$ value of the group element.
* This is for most representation the projective $X$ coordinate.
*
* @return The X value.
* @return The $X$ value.
*/
public FieldElement getX() {
return this.X;
}
/**
* Gets the Y value of the group element.
* This is for most representation the projective Y coordinate.
* Gets the $Y$ value of the group element.
* This is for most representation the projective $Y$ coordinate.
*
* @return The Y value.
* @return The $Y$ value.
*/
public FieldElement getY() {
return this.Y;
}
/**
* Gets the Z value of the group element.
* This is for most representation the projective Z coordinate.
* Gets the $Z$ value of the group element.
* This is for most representation the projective $Z$ coordinate.
*
* @return The Z value.
* @return The $Z$ value.
*/
public FieldElement getZ() {
return this.Z;
}
/**
* Gets the T value of the group element.
* This is for most representation the projective T coordinate.
* Gets the $T$ value of the group element.
* This is for most representation the projective $T$ coordinate.
*
* @return The T value.
* @return The $T$ value.
*/
public FieldElement getT() {
return this.T;
@ -470,14 +481,14 @@ public class GroupElement implements Serializable {
/**
* Convert a GroupElement from one Representation to another.
* TODO-CR: Add additional conversion?
* r = p
* $r = p$
* <p>
* Supported conversions:
* </p><ul>
* <li>P3 -> P2
* <li>P3 -> CACHED (1 multiply, 1 add, 1 subtract)
* <li>P1P1 -> P2 (3 multiply)
* <li>P1P1 -> P3 (4 multiply)
* <p><ul>
* <li>P3 $\rightarrow$ P2
* <li>P3 $\rightarrow$ CACHED (1 multiply, 1 add, 1 subtract)
* <li>P1P1 $\rightarrow$ P2 (3 multiply)
* <li>P1P1 $\rightarrow$ P3 (4 multiply)
*
* @param repr The representation to convert to.
* @return A new group element in the given representation.
@ -573,33 +584,35 @@ public class GroupElement implements Serializable {
}
/**
* Doubles a given group element p in P^2 or P^3 representation and returns the result in P x P representation.
* r = 2 * p where p = (X : Y : Z) or p = (X : Y : Z : T)
* Doubles a given group element $p$ in $P^2$ or $P^3$ representation and returns the result in $P \times P$ representation.
* $r = 2 * p$ where $p = (X : Y : Z)$ or $p = (X : Y : Z : T)$
* <p>
* r in P x P representation:
* $r$ in $P \times P$ representation:
* <p>
* r = ((X' : Z'), (Y' : T')) where
* $r = ((X' : Z'), (Y' : T'))$ where
* </p><ul>
* <li>X' = (X + Y)^2 - (Y^2 + X^2)
* <li>Y' = Y^2 + X^2
* <li>Z' = y^2 - X^2
* <li>T' = 2 * Z^2 - (y^2 - X^2)
* <li>$X' = (X + Y)^2 - (Y^2 + X^2)$
* <li>$Y' = Y^2 + X^2$
* <li>$Z' = y^2 - X^2$
* <li>$T' = 2 * Z^2 - (y^2 - X^2)$
* </ul><p>
* r converted from P x P to P^2 representation:
* $r$ converted from $P \times P$ to $P^2$ representation:
* <p>
* r = (X'' : Y'' : Z'') where
* $r = (X'' : Y'' : Z'')$ where
* </p><ul>
* <li>X'' = X' * Z' = ((X + Y)^2 - Y^2 - X^2) * (2 * Z^2 - (y^2 - X^2))
* <li>Y'' = Y' * T' = (Y^2 + X^2) * (2 * Z^2 - (y^2 - X^2))
* <li>Z'' = Z' * T' = (y^2 - X^2) * (2 * Z^2 - (y^2 - X^2))
* <li>$X'' = X' * Z' = ((X + Y)^2 - Y^2 - X^2) * (2 * Z^2 - (y^2 - X^2))$
* <li>$Y'' = Y' * T' = (Y^2 + X^2) * (2 * Z^2 - (y^2 - X^2))$
* <li>$Z'' = Z' * T' = (y^2 - X^2) * (2 * Z^2 - (y^2 - X^2))$
* </ul><p>
* Formula for the P^2 representation is in agreement with the formula given in [4] page 12 (with a = -1)
* Formula for the $P^2$ representation is in agreement with the formula given in [4] page 12 (with $a = -1$)
* up to a common factor -1 which does not matter:
* <p>
* B = (X + Y)^2; C = X^2; D = Y^2; E = -C = -X^2; F := E + D = Y^2 - X^2; H = Z^2; J = F 2 * H;
* X3 = (B C D) · J = X' * (-T');
* Y3 = F · (E D) = Z' * (-Y');
* $$
* B = (X + Y)^2; C = X^2; D = Y^2; E = -C = -X^2; F := E + D = Y^2 - X^2; H = Z^2; J = F 2 * H; \\
* X3 = (B C D) · J = X' * (-T'); \\
* Y3 = F · (E D) = Z' * (-Y'); \\
* Z3 = F · J = Z' * (-T').
* $$
*
* @return The P1P1 representation
*/
@ -625,41 +638,43 @@ public class GroupElement implements Serializable {
* GroupElement addition using the twisted Edwards addition law with
* extended coordinates (Hisil2008).
* <p>
* this must be in P^3 representation and q in PRECOMP representation.
* r = p + q where p = this = (X1 : Y1 : Z1 : T1), q = (q.X, q.Y, q.Z) = (Y2/Z2 + X2/Z2, Y2/Z2 - X2/Z2, 2 * d * X2/Z2 * Y2/Z2)
* this must be in $P^3$ representation and $q$ in PRECOMP representation.
* $r = p + q$ where $p = this = (X1 : Y1 : Z1 : T1), q = (q.X, q.Y, q.Z) = (Y2/Z2 + X2/Z2, Y2/Z2 - X2/Z2, 2 * d * X2/Z2 * Y2/Z2)$
* <p>
* r in P x P representation:
* $r$ in $P \times P$ representation:
* <p>
* r = ((X' : Z'), (Y' : T')) where
* </p><ul>
* <li>X' = (Y1 + X1) * q.X - (Y1 - X1) * q.Y = ((Y1 + X1) * (Y2 + X2) - (Y1 - X1) * (Y2 - X2)) * 1/Z2
* <li>Y' = (Y1 + X1) * q.X + (Y1 - X1) * q.Y = ((Y1 + X1) * (Y2 + X2) + (Y1 - X1) * (Y2 - X2)) * 1/Z2
* <li>Z' = 2 * Z1 + T1 * q.Z = 2 * Z1 + T1 * 2 * d * X2 * Y2 * 1/Z2^2 = (2 * Z1 * Z2 + 2 * d * T1 * T2) * 1/Z2
* <li>T' = 2 * Z1 - T1 * q.Z = 2 * Z1 - T1 * 2 * d * X2 * Y2 * 1/Z2^2 = (2 * Z1 * Z2 - 2 * d * T1 * T2) * 1/Z2
* $r = ((X' : Z'), (Y' : T'))$ where
* <p><ul>
* <li>$X' = (Y1 + X1) * q.X - (Y1 - X1) * q.Y = ((Y1 + X1) * (Y2 + X2) - (Y1 - X1) * (Y2 - X2)) * 1/Z2$
* <li>$Y' = (Y1 + X1) * q.X + (Y1 - X1) * q.Y = ((Y1 + X1) * (Y2 + X2) + (Y1 - X1) * (Y2 - X2)) * 1/Z2$
* <li>$Z' = 2 * Z1 + T1 * q.Z = 2 * Z1 + T1 * 2 * d * X2 * Y2 * 1/Z2^2 = (2 * Z1 * Z2 + 2 * d * T1 * T2) * 1/Z2$
* <li>$T' = 2 * Z1 - T1 * q.Z = 2 * Z1 - T1 * 2 * d * X2 * Y2 * 1/Z2^2 = (2 * Z1 * Z2 - 2 * d * T1 * T2) * 1/Z2$
* </ul><p>
* Setting A = (Y1 - X1) * (Y2 - X2), B = (Y1 + X1) * (Y2 + X2), C = 2 * d * T1 * T2, D = 2 * Z1 * Z2 we get
* </p><ul>
* <li>X' = (B - A) * 1/Z2
* <li>Y' = (B + A) * 1/Z2
* <li>Z' = (D + C) * 1/Z2
* <li>T' = (D - C) * 1/Z2
* Setting $A = (Y1 - X1) * (Y2 - X2), B = (Y1 + X1) * (Y2 + X2), C = 2 * d * T1 * T2, D = 2 * Z1 * Z2$ we get
* <p><ul>
* <li>$X' = (B - A) * 1/Z2$
* <li>$Y' = (B + A) * 1/Z2$
* <li>$Z' = (D + C) * 1/Z2$
* <li>$T' = (D - C) * 1/Z2$
* </ul><p>
* r converted from P x P to P^2 representation:
* $r$ converted from $P \times P$ to $P^2$ representation:
* <p>
* r = (X'' : Y'' : Z'' : T'') where
* </p><ul>
* <li>X'' = X' * Z' = (B - A) * (D + C) * 1/Z2^2
* <li>Y'' = Y' * T' = (B + A) * (D - C) * 1/Z2^2
* <li>Z'' = Z' * T' = (D + C) * (D - C) * 1/Z2^2
* <li>T'' = X' * Y' = (B - A) * (B + A) * 1/Z2^2
* $r = (X'' : Y'' : Z'' : T'')$ where
* <p><ul>
* <li>$X'' = X' * Z' = (B - A) * (D + C) * 1/Z2^2$
* <li>$Y'' = Y' * T' = (B + A) * (D - C) * 1/Z2^2$
* <li>$Z'' = Z' * T' = (D + C) * (D - C) * 1/Z2^2$
* <li>$T'' = X' * Y' = (B - A) * (B + A) * 1/Z2^2$
* </ul><p>
* TODO-CR BR: Formula for the P^2 representation is not in agreement with the formula given in [2] page 6<br>
* TODO-CR BR: (the common factor 1/Z2^2 does not matter):<br>
* E = B - A, F = D - C, G = D + C, H = B + A<br>
* X3 = E * F = (B - A) * (D - C);
* Y3 = G * H = (D + C) * (B + A);
* Z3 = F * G = (D - C) * (D + C);
* TODO-CR BR: Formula for the $P^2$ representation is not in agreement with the formula given in [2] page 6<br>
* TODO-CR BR: (the common factor $1/Z2^2$ does not matter):<br>
* $$
* E = B - A, F = D - C, G = D + C, H = B + A \\
* X3 = E * F = (B - A) * (D - C); \\
* Y3 = G * H = (D + C) * (B + A); \\
* Z3 = F * G = (D - C) * (D + C); \\
* T3 = E * H = (B - A) * (B + A);
* $$
*
* @param q the PRECOMP representation of the GroupElement to add.
* @return the P1P1 representation of the result.
@ -684,10 +699,10 @@ public class GroupElement implements Serializable {
* GroupElement subtraction using the twisted Edwards addition law with
* extended coordinates (Hisil2008).
* <p>
* this must be in P^3 representation and q in PRECOMP representation.
* r = p - q where p = this = (X1 : Y1 : Z1 : T1), q = (q.X, q.Y, q.Z) = (Y2/Z2 + X2/Z2, Y2/Z2 - X2/Z2, 2 * d * X2/Z2 * Y2/Z2)
* this must be in $P^3$ representation and $q$ in PRECOMP representation.
* $r = p - q$ where $p = this = (X1 : Y1 : Z1 : T1), q = (q.X, q.Y, q.Z) = (Y2/Z2 + X2/Z2, Y2/Z2 - X2/Z2, 2 * d * X2/Z2 * Y2/Z2)$
* <p>
* Negating q means negating the value of X2 and T2 (the latter is irrelevant here).
* Negating $q$ means negating the value of $X2$ and $T2$ (the latter is irrelevant here).
* The formula is in accordance to {@link #madd the above addition}.
*
* @param q the PRECOMP representation of the GroupElement to subtract.
@ -713,22 +728,22 @@ public class GroupElement implements Serializable {
* GroupElement addition using the twisted Edwards addition law with
* extended coordinates (Hisil2008).
* <p>
* this must be in P^3 representation and q in CACHED representation.
* r = p + q where p = this = (X1 : Y1 : Z1 : T1), q = (q.X, q.Y, q.Z, q.T) = (Y2 + X2, Y2 - X2, Z2, 2 * d * T2)
* this must be in $P^3$ representation and $q$ in CACHED representation.
* $r = p + q$ where $p = this = (X1 : Y1 : Z1 : T1), q = (q.X, q.Y, q.Z, q.T) = (Y2 + X2, Y2 - X2, Z2, 2 * d * T2)$
* <p>
* r in P x P representation:
* $r$ in $P \times P$ representation:
* </p><ul>
* <li>X' = (Y1 + X1) * (Y2 + X2) - (Y1 - X1) * (Y2 - X2)
* <li>Y' = (Y1 + X1) * (Y2 + X2) + (Y1 - X1) * (Y2 - X2)
* <li>Z' = 2 * Z1 * Z2 + 2 * d * T1 * T2
* <li>T' = 2 * Z1 * T2 - 2 * d * T1 * T2
* <li>$X' = (Y1 + X1) * (Y2 + X2) - (Y1 - X1) * (Y2 - X2)$
* <li>$Y' = (Y1 + X1) * (Y2 + X2) + (Y1 - X1) * (Y2 - X2)$
* <li>$Z' = 2 * Z1 * Z2 + 2 * d * T1 * T2$
* <li>$T' = 2 * Z1 * T2 - 2 * d * T1 * T2$
* </ul><p>
* Setting A = (Y1 - X1) * (Y2 - X2), B = (Y1 + X1) * (Y2 + X2), C = 2 * d * T1 * T2, D = 2 * Z1 * Z2 we get
* Setting $A = (Y1 - X1) * (Y2 - X2), B = (Y1 + X1) * (Y2 + X2), C = 2 * d * T1 * T2, D = 2 * Z1 * Z2$ we get
* </p><ul>
* <li>X' = (B - A)
* <li>Y' = (B + A)
* <li>Z' = (D + C)
* <li>T' = (D - C)
* <li>$X' = (B - A)$
* <li>$Y' = (B + A)$
* <li>$Z' = (D + C)$
* <li>$T' = (D - C)$
* </ul><p>
* Same result as in {@link #madd} (up to a common factor which does not matter).
*
@ -756,9 +771,9 @@ public class GroupElement implements Serializable {
* GroupElement subtraction using the twisted Edwards addition law with
* extended coordinates (Hisil2008).
* <p>
* r = p - q
* $r = p - q$
* <p>
* Negating q means negating the value of the coordinate X2 and T2.
* Negating $q$ means negating the value of the coordinate $X2$ and $T2$.
* The formula is in accordance to {@link #add the above addition}.
*
* @param q the PRECOMP representation of the GroupElement to subtract.
@ -784,7 +799,7 @@ public class GroupElement implements Serializable {
/**
* Negates this group element by subtracting it from the neutral group element.
* <p>
* TODO-CR BR: why not simply negate the coordinates X and T?
* TODO-CR BR: why not simply negate the coordinates $X$ and $T$?
*
* @return The negative of this group element.
*/
@ -852,7 +867,7 @@ public class GroupElement implements Serializable {
* <p>
* Method is package private only so that tests run.
*
* @param a = a[0]+256*a[1]+...+256^31 a[31]
* @param a $= a[0]+256*a[1]+...+256^{31} a[31]$
* @return 64 bytes, each between -8 and 7
*/
static byte[] toRadix16(final byte[] a) {
@ -880,21 +895,21 @@ public class GroupElement implements Serializable {
/**
* Constant-time conditional move.
* <p>
* Replaces this with u if b == 1.<br>
* Replaces this with this if b == 0.
* Replaces this with $u$ if $b == 1$.<br>
* Replaces this with this if $b == 0$.
* <p>
* Method is package private only so that tests run.
*
* @param u The group element to return if b == 1.
* @param b in {0, 1}
* @return u if b == 1; this if b == 0; Results undefined if b is not in {0, 1}.
* @param u The group element to return if $b == 1$.
* @param b in $\{0, 1\}$
* @return $u$ if $b == 1$; this if $b == 0$. Results undefined if $b$ is not in $\{0, 1\}$.
*/
GroupElement cmov(final GroupElement u, final int b) {
return precomp(curve, X.cmov(u.X, b), Y.cmov(u.Y, b), Z.cmov(u.Z, b));
}
/**
* Look up 16^i r_i B in the precomputed table.
* Look up $16^i r_i B$ in the precomputed table.
* <p>
* No secret array indices, no secret branching.
* Constant time.
@ -903,8 +918,8 @@ public class GroupElement implements Serializable {
* <p>
* Method is package private only so that tests run.
*
* @param pos = i/2 for i in {0, 2, 4,..., 62}
* @param b = r_i
* @param pos $= i/2$ for $i$ in $\{0, 2, 4,..., 62\}$
* @param b $= r_i$
* @return the GroupElement
*/
GroupElement select(final int pos, final int b) {
@ -930,14 +945,14 @@ public class GroupElement implements Serializable {
}
/**
* h = a * B where a = a[0]+256*a[1]+...+256^31 a[31] and
* B is this point. If its lookup table has not been precomputed, it
* will be at the start of the method (and cached for later calls).
* $h = a * B$ where $a = a[0]+256*a[1]+\dots+256^{31} a[31]$ and
* $B$ is this point. If its lookup table has not been precomputed, it
* will be at the start of the method (and cached for later calls).
* Constant time.
* <p>
* Preconditions: (TODO: Check this applies here)
* a[31] &lt;= 127
* @param a = a[0]+256*a[1]+...+256^31 a[31]
* $a[31] \le 127$
* @param a $= a[0]+256*a[1]+\dots+256^{31} a[31]$
* @return the GroupElement
*/
public GroupElement scalarMultiply(final byte[] a) {
@ -963,16 +978,16 @@ public class GroupElement implements Serializable {
}
/**
* Calculates a sliding-windows base 2 representation for a given value a.
* Calculates a sliding-windows base 2 representation for a given value $a$.
* To learn more about it see [6] page 8.
* <p>
* Output: r which satisfies
* a = r0 * 2^0 + r1 * 2^1 + ... + r255 * 2^255 with ri in {-15, -13, -11, -9, -7, -5, -3, -1, 0, 1, 3, 5, 7, 9, 11, 13, 15}
* Output: $r$ which satisfies
* $a = r0 * 2^0 + r1 * 2^1 + \dots + r255 * 2^{255}$ with $ri$ in $\{-15, -13, -11, -9, -7, -5, -3, -1, 0, 1, 3, 5, 7, 9, 11, 13, 15\}$
* <p>
* Method is package private only so that tests run.
*
* @param a = a[0]+256*a[1]+...+256^31 a[31].
* @return The byte array r in the above described form.
* @param a $= a[0]+256*a[1]+\dots+256^{31} a[31]$.
* @return The byte array $r$ in the above described form.
*/
static byte[] slide(final byte[] a) {
byte[] r = new byte[256];
@ -1011,14 +1026,14 @@ public class GroupElement implements Serializable {
}
/**
* r = a * A + b * B where a = a[0]+256*a[1]+...+256^31 a[31],
* b = b[0]+256*b[1]+...+256^31 b[31] and B is this point.
* $r = a * A + b * B$ where $a = a[0]+256*a[1]+\dots+256^{31} a[31]$,
* $b = b[0]+256*b[1]+\dots+256^{31} b[31]$ and $B$ is this point.
* <p>
* A must have been previously precomputed.
* $A$ must have been previously precomputed.
*
* @param A in P3 representation.
* @param a = a[0]+256*a[1]+...+256^31 a[31]
* @param b = b[0]+256*b[1]+...+256^31 b[31]
* @param a $= a[0]+256*a[1]+\dots+256^{31} a[31]$
* @param b $= b[0]+256*b[1]+\dots+256^{31} b[31]$
* @return the GroupElement
*/
public GroupElement doubleScalarMultiplyVariableTime(final GroupElement A, final byte[] a, final byte[] b) {

View File

@ -1,30 +1,39 @@
/**
* EdDSA-Java by str4d
*
* To the extent possible under law, the person who associated CC0 with
* EdDSA-Java has waived all copyright and related or neighboring rights
* to EdDSA-Java.
*
* You should have received a copy of the CC0 legalcode along with this
* work. If not, see <https://creativecommons.org/publicdomain/zero/1.0/>.
*
*/
package net.i2p.crypto.eddsa.math;
import java.io.Serializable;
/**
*
* @since 0.9.15
*
*/
public interface ScalarOps extends Serializable {
/**
* Reduce the given scalar mod l.
* Reduce the given scalar mod $l$.
* <p>
* From the Ed25519 paper:<br>
* Here we interpret 2b-bit strings in little-endian form as integers in
* {0, 1,..., 2^(2b)-1}.
* @param s
* @return s mod l
* Here we interpret $2b$-bit strings in little-endian form as integers in
* $\{0, 1,..., 2^{(2b)}-1\}$.
* @param s the scalar to reduce
* @return $s \bmod l$
*/
public byte[] reduce(byte[] s);
/**
* r = (a * b + c) mod l
* @param a
* @param b
* @param c
* @return (a*b + c) mod l
* $r = (a * b + c) \bmod l$
* @param a a scalar
* @param b a scalar
* @param c a scalar
* @return $(a*b + c) \bmod l$
*/
public byte[] multiplyAndAdd(byte[] a, byte[] b, byte[] c);
}

View File

@ -1,3 +1,14 @@
/**
* EdDSA-Java by str4d
*
* To the extent possible under law, the person who associated CC0 with
* EdDSA-Java has waived all copyright and related or neighboring rights
* to EdDSA-Java.
*
* You should have received a copy of the CC0 legalcode along with this
* work. If not, see <https://creativecommons.org/publicdomain/zero/1.0/>.
*
*/
package net.i2p.crypto.eddsa.math.bigint;
import java.io.Serializable;

View File

@ -1,3 +1,14 @@
/**
* EdDSA-Java by str4d
*
* To the extent possible under law, the person who associated CC0 with
* EdDSA-Java has waived all copyright and related or neighboring rights
* to EdDSA-Java.
*
* You should have received a copy of the CC0 legalcode along with this
* work. If not, see <https://creativecommons.org/publicdomain/zero/1.0/>.
*
*/
package net.i2p.crypto.eddsa.math.bigint;
import java.io.Serializable;
@ -25,10 +36,11 @@ public class BigIntegerLittleEndianEncoding extends Encoding implements Serializ
}
/**
* Convert x to little endian.
* Convert $x$ to little endian.
* Constant time.
*
* @return array of length b/8
* @param x the BigInteger value to encode
* @return array of length $b/8$
* @throws IllegalStateException if field not set
*/
public byte[] encode(BigInteger x) {
@ -46,10 +58,10 @@ public class BigIntegerLittleEndianEncoding extends Encoding implements Serializ
}
/**
* Decode a FieldElement from its (b-1)-bit encoding.
* Decode a FieldElement from its $(b-1)$-bit encoding.
* The highest bit is masked out.
*
* @param in the (b-1)-bit encoding of a FieldElement.
* @param in the $(b-1)$-bit encoding of a FieldElement.
* @return the FieldElement represented by 'val'.
* @throws IllegalStateException if field not set
* @throws IllegalArgumentException if encoding is invalid
@ -64,6 +76,9 @@ public class BigIntegerLittleEndianEncoding extends Encoding implements Serializ
/**
* Convert in to big endian
*
* @param in the $(b-1)$-bit encoding of a FieldElement.
* @return the decoded value as a BigInteger
*/
public BigInteger toBigInteger(byte[] in) {
byte[] out = new byte[in.length];
@ -75,10 +90,10 @@ public class BigIntegerLittleEndianEncoding extends Encoding implements Serializ
/**
* From the Ed25519 paper:<br>
* x is negative if the (b-1)-bit encoding of x is lexicographically larger
* than the (b-1)-bit encoding of -x. If q is an odd prime and the encoding
* is the little-endian representation of {0, 1,..., q-1} then the negative
* elements of F_q are {1, 3, 5,..., q-2}.
* $x$ is negative if the $(b-1)$-bit encoding of $x$ is lexicographically larger
* than the $(b-1)$-bit encoding of $-x$. If $q$ is an odd prime and the encoding
* is the little-endian representation of $\{0, 1,\dots, q-1\}$ then the negative
* elements of $F_q$ are $\{1, 3, 5,\dots, q-2\}$.
* @return true if negative
*/
public boolean isNegative(FieldElement x) {

View File

@ -1,3 +1,14 @@
/**
* EdDSA-Java by str4d
*
* To the extent possible under law, the person who associated CC0 with
* EdDSA-Java has waived all copyright and related or neighboring rights
* to EdDSA-Java.
*
* You should have received a copy of the CC0 legalcode along with this
* work. If not, see <https://creativecommons.org/publicdomain/zero/1.0/>.
*
*/
package net.i2p.crypto.eddsa.math.bigint;
import java.math.BigInteger;

View File

@ -1,3 +1,14 @@
/**
* EdDSA-Java by str4d
*
* To the extent possible under law, the person who associated CC0 with
* EdDSA-Java has waived all copyright and related or neighboring rights
* to EdDSA-Java.
*
* You should have received a copy of the CC0 legalcode along with this
* work. If not, see <https://creativecommons.org/publicdomain/zero/1.0/>.
*
*/
package net.i2p.crypto.eddsa.math.ed25519;
import net.i2p.crypto.eddsa.Utils;
@ -6,11 +17,11 @@ import net.i2p.crypto.eddsa.math.*;
import java.util.Arrays;
/**
* Class to represent a field element of the finite field p=2^255-19 elements.
* Class to represent a field element of the finite field $p = 2^{255} - 19$ elements.
* <p>
* An element t, entries t[0]...t[9], represents the integer
* t[0]+2^26 t[1]+2^51 t[2]+2^77 t[3]+2^102 t[4]+...+2^230 t[9].
* Bounds on each t[i] vary depending on context.
* An element $t$, entries $t[0] \dots t[9]$, represents the integer
* $t[0]+2^{26} t[1]+2^{51} t[2]+2^{77} t[3]+2^{102} t[4]+\dots+2^{230} t[9]$.
* Bounds on each $t[i]$ vary depending on context.
* <p>
* Reviewed/commented by Bloody Rookie (nemproject@gmx.de)
*/
@ -23,8 +34,8 @@ public class Ed25519FieldElement extends FieldElement {
/**
* Creates a field element.
*
* @param f The underlying field, must be the finite field with p = 2^255 - 19 elements
* @param t The 2^25.5 bit representation of the field element.
* @param f The underlying field, must be the finite field with $p = 2^{255} - 19$ elements
* @param t The $2^{25.5}$ bit representation of the field element.
*/
public Ed25519FieldElement(Field f, int[] t) {
super(f);
@ -46,18 +57,18 @@ public class Ed25519FieldElement extends FieldElement {
}
/**
* h = f + g
* $h = f + g$
* <p>
* TODO-CR BR: h is allocated via new, probably not a good idea. Do we need the copying into temp variables if we do that?
* TODO-CR BR: $h$ is allocated via new, probably not a good idea. Do we need the copying into temp variables if we do that?
* <p>
* Preconditions:
* </p><ul>
* <li>|f| bounded by 1.1*2^25,1.1*2^24,1.1*2^25,1.1*2^24,etc.
* <li>|g| bounded by 1.1*2^25,1.1*2^24,1.1*2^25,1.1*2^24,etc.
* <li>$|f|$ bounded by $1.1*2^{25},1.1*2^{24},1.1*2^{25},1.1*2^{24},$ etc.
* <li>$|g|$ bounded by $1.1*2^{25},1.1*2^{24},1.1*2^{25},1.1*2^{24},$ etc.
* </ul><p>
* Postconditions:
* </p><ul>
* <li>|h| bounded by 1.1*2^26,1.1*2^25,1.1*2^26,1.1*2^25,etc.
* <li>$|h|$ bounded by $1.1*2^{26},1.1*2^{25},1.1*2^{26},1.1*2^{25},$ etc.
* </ul>
*
* @param val The field element to add.
@ -73,20 +84,20 @@ public class Ed25519FieldElement extends FieldElement {
}
/**
* h = f - g
* $h = f - g$
* <p>
* Can overlap h with f or g.
* Can overlap $h$ with $f$ or $g$.
* <p>
* TODO-CR BR: See above.
* <p>
* Preconditions:
* </p><ul>
* <li>|f| bounded by 1.1*2^25,1.1*2^24,1.1*2^25,1.1*2^24,etc.
* <li>|g| bounded by 1.1*2^25,1.1*2^24,1.1*2^25,1.1*2^24,etc.
* <li>$|f|$ bounded by $1.1*2^{25},1.1*2^{24},1.1*2^{25},1.1*2^{24},$ etc.
* <li>$|g|$ bounded by $1.1*2^{25},1.1*2^{24},1.1*2^{25},1.1*2^{24},$ etc.
* </ul><p>
* Postconditions:
* </p><ul>
* <li>|h| bounded by 1.1*2^26,1.1*2^25,1.1*2^26,1.1*2^25,etc.
* <li>$|h|$ bounded by $1.1*2^{26},1.1*2^{25},1.1*2^{26},1.1*2^{25},$ etc.
* </ul>
*
* @param val The field element to subtract.
@ -102,17 +113,17 @@ public class Ed25519FieldElement extends FieldElement {
}
/**
* h = -f
* $h = -f$
* <p>
* TODO-CR BR: see above.
* <p>
* Preconditions:
* </p><ul>
* <li>|f| bounded by 1.1*2^25,1.1*2^24,1.1*2^25,1.1*2^24,etc.
* <li>$|f|$ bounded by $1.1*2^{25},1.1*2^{24},1.1*2^{25},1.1*2^{24},$ etc.
* </ul><p>
* Postconditions:
* </p><ul>
* <li>|h| bounded by 1.1*2^25,1.1*2^24,1.1*2^25,1.1*2^24,etc.
* <li>$|h|$ bounded by $1.1*2^{25},1.1*2^{24},1.1*2^{25},1.1*2^{24},$ etc.
* </ul>
*
* @return The field element (-1) * this.
@ -126,21 +137,21 @@ public class Ed25519FieldElement extends FieldElement {
}
/**
* h = f * g
* $h = f * g$
* <p>
* Can overlap h with f or g.
* Can overlap $h$ with $f$ or $g$.
* <p>
* Preconditions:
* </p><ul>
* <li>|f| bounded by
* 1.65*2^26,1.65*2^25,1.65*2^26,1.65*2^25,etc.
* <li>|g| bounded by
* 1.65*2^26,1.65*2^25,1.65*2^26,1.65*2^25,etc.
* <li>$|f|$ bounded by
* $1.65*2^{26},1.65*2^{25},1.65*2^{26},1.65*2^{25},$ etc.
* <li>$|g|$ bounded by
* $1.65*2^{26},1.65*2^{25},1.65*2^{26},1.65*2^{25},$ etc.
* </ul><p>
* Postconditions:
* </p><ul>
* <li>|h| bounded by
* 1.01*2^25,1.01*2^24,1.01*2^25,1.01*2^24,etc.
* <li>$|h|$ bounded by
* $1.01*2^{25},1.01*2^{24},1.01*2^{25},1.01*2^{24},$ etc.
* </ul><p>
* Notes on implementation strategy:
* <p>
@ -377,17 +388,17 @@ public class Ed25519FieldElement extends FieldElement {
}
/**
* h = f * f
* $h = f * f$
* <p>
* Can overlap h with f.
* Can overlap $h$ with $f$.
* <p>
* Preconditions:
* </p><ul>
* <li>|f| bounded by 1.65*2^26,1.65*2^25,1.65*2^26,1.65*2^25,etc.
* <li>$|f|$ bounded by $1.65*2^{26},1.65*2^{25},1.65*2^{26},1.65*2^{25},$ etc.
* </ul><p>
* Postconditions:
* </p><ul>
* <li>|h| bounded by 1.01*2^25,1.01*2^24,1.01*2^25,1.01*2^24,etc.
* <li>$|h|$ bounded by $1.01*2^{25},1.01*2^{24},1.01*2^{25},1.01*2^{24},$ etc.
* </ul><p>
* See {@link #multiply(FieldElement)} for discussion
* of implementation strategy.
@ -533,17 +544,17 @@ public class Ed25519FieldElement extends FieldElement {
}
/**
* h = 2 * f * f
* $h = 2 * f * f$
* <p>
* Can overlap h with f.
* Can overlap $h$ with $f$.
* <p>
* Preconditions:
* </p><ul>
* <li>|f| bounded by 1.65*2^26,1.65*2^25,1.65*2^26,1.65*2^25,etc.
* <li>$|f|$ bounded by $1.65*2^{26},1.65*2^{25},1.65*2^{26},1.65*2^{25},$ etc.
* </ul><p>
* Postconditions:
* </p><ul>
* <li>|h| bounded by 1.01*2^25,1.01*2^24,1.01*2^25,1.01*2^24,etc.
* <li>$|h|$ bounded by $1.01*2^{25},1.01*2^{24},1.01*2^{25},1.01*2^{24},$ etc.
* </ul><p>
* See {@link #multiply(FieldElement)} for discussion
* of implementation strategy.
@ -698,7 +709,7 @@ public class Ed25519FieldElement extends FieldElement {
* Invert this field element.
* <p>
* The inverse is found via Fermat's little theorem:<br>
* a^p congruent a mod p and therefore a^(p-2) congruent a^-1 mod p
* $a^p \cong a \mod p$ and therefore $a^{(p-2)} \cong a^{-1} \mod p$
*
* @return The inverse of this field element.
*/
@ -816,12 +827,12 @@ public class Ed25519FieldElement extends FieldElement {
}
/**
* Gets this field element to the power of (2^252 - 3).
* Gets this field element to the power of $(2^{252} - 3)$.
* This is a helper function for calculating the square root.
* <p>
* TODO-CR BR: I think it makes sense to have a sqrt function.
*
* @return This field element to the power of (2^252 - 3).
* @return This field element to the power of $(2^{252} - 3)$.
*/
public FieldElement pow22523() {
FieldElement t0, t1, t2;
@ -941,7 +952,7 @@ public class Ed25519FieldElement extends FieldElement {
*
* @param val the other field element.
* @param b must be 0 or 1, otherwise results are undefined.
* @return a copy of this if b == 0, or a copy of val if b == 1.
* @return a copy of this if $b == 0$, or a copy of val if $b == 1$.
* @since 0.9.36
*/
@Override

View File

@ -1,3 +1,14 @@
/**
* EdDSA-Java by str4d
*
* To the extent possible under law, the person who associated CC0 with
* EdDSA-Java has waived all copyright and related or neighboring rights
* to EdDSA-Java.
*
* You should have received a copy of the CC0 legalcode along with this
* work. If not, see <https://creativecommons.org/publicdomain/zero/1.0/>.
*
*/
package net.i2p.crypto.eddsa.math.ed25519;
import net.i2p.crypto.eddsa.math.*;
@ -9,40 +20,60 @@ import net.i2p.crypto.eddsa.math.*;
*/
public class Ed25519LittleEndianEncoding extends Encoding {
/**
* Encodes a given field element in its 32 byte representation. This is done in TWO steps.
* Step 1: Reduce the value of the field element modulo p.
* Step 2: Convert the field element to the 32 byte representation.
* <p>
* The idea for the modulo p reduction algorithm is as follows:
* <p>
* Assumption:
* </p><ul>
* <li>p = 2^255 - 19
* <li>h = h0 + 2^25 * h1 + 2^(26+25) * h2 + ... + 2^230 * h9 where 0 &lt;= |hi| &lt; 2^27 for all i=0,...,9.
* <li>h congruent r modulo p, i.e. h = r + q * p for some suitable 0 &lt;= r &lt; p and an integer q.
* Encodes a given field element in its 32 byte representation. This is done in two steps:
* <ol>
* <li>Reduce the value of the field element modulo $p$.
* <li>Convert the field element to the 32 byte representation.
* </ol><p>
* The idea for the modulo $p$ reduction algorithm is as follows:
* </p>
* <h2>Assumption:</h2>
* <ul>
* <li>$p = 2^{255} - 19$
* <li>$h = h_0 + 2^{25} * h_1 + 2^{(26+25)} * h_2 + \dots + 2^{230} * h_9$ where $0 \le |h_i| \lt 2^{27}$ for all $i=0,\dots,9$.
* <li>$h \cong r \mod p$, i.e. $h = r + q * p$ for some suitable $0 \le r \lt p$ and an integer $q$.
* </ul><p>
* Then q = [2^-255 * (h + 19 * 2^-25 * h9 + 1/2)] where [x] = floor(x).
* <p>
* Proof:
* Then $q = [2^{-255} * (h + 19 * 2^{-25} * h_9 + 1/2)]$ where $[x] = floor(x)$.
* </p>
* <h2>Proof:</h2>
* <p>
* We begin with some very raw estimation for the bounds of some expressions:
* <pre>|h| &lt; 2^230 * 2^30 = 2^260 ==&gt; |r + q * p| &lt; 2^260 ==&gt; |q| &lt; 2^10.
* ==&gt; -1/4 &lt;= a := 19^2 * 2^-255 * q &lt; 1/4.
* |h - 2^230 * h9| = |h0 + ... + 2^204 * h8| &lt; 2^204 * 2^30 = 2^234.
* ==&gt; -1/4 &lt;= b := 19 * 2^-255 * (h - 2^230 * h9) &lt; 1/4</pre>
* Therefore 0 &lt; 1/2 - a - b &lt; 1.
* <p>
* Set x := r + 19 * 2^-255 * r + 1/2 - a - b then
* 0 &lt;= x &lt; 255 - 20 + 19 + 1 = 2^255 ==&gt; 0 &lt;= 2^-255 * x &lt; 1. Since q is an integer we have
*
* <pre>[q + 2^-255 * x] = q (1)</pre>
* $$
* \begin{equation}
* |h| \lt 2^{230} * 2^{30} = 2^{260} \Rightarrow |r + q * p| \lt 2^{260} \Rightarrow |q| \lt 2^{10}. \\
* \Rightarrow -1/4 \le a := 19^2 * 2^{-255} * q \lt 1/4. \\
* |h - 2^{230} * h_9| = |h_0 + \dots + 2^{204} * h_8| \lt 2^{204} * 2^{30} = 2^{234}. \\
* \Rightarrow -1/4 \le b := 19 * 2^{-255} * (h - 2^{230} * h_9) \lt 1/4
* \end{equation}
* $$
* <p>
* Have a closer look at x:
* <pre>x = h - q * (2^255 - 19) + 19 * 2^-255 * (h - q * (2^255 - 19)) + 1/2 - 19^2 * 2^-255 * q - 19 * 2^-255 * (h - 2^230 * h9)
* = h - q * 2^255 + 19 * q + 19 * 2^-255 * h - 19 * q + 19^2 * 2^-255 * q + 1/2 - 19^2 * 2^-255 * q - 19 * 2^-255 * h + 19 * 2^-25 * h9
* = h + 19 * 2^-25 * h9 + 1/2 - q^255.</pre>
* Therefore $0 \lt 1/2 - a - b \lt 1$.
* <p>
* Inserting the expression for x into (1) we get the desired expression for q.
* Set $x := r + 19 * 2^{-255} * r + 1/2 - a - b$. Then:
* <p>
* $$
* 0 \le x \lt 255 - 20 + 19 + 1 = 2^{255} \\
* \Rightarrow 0 \le 2^{-255} * x \lt 1.
* $$
* <p>
* Since $q$ is an integer we have
* <p>
* $$
* [q + 2^{-255} * x] = q \quad (1)
* $$
* <p>
* Have a closer look at $x$:
* <p>
* $$
* \begin{align}
* x &amp;= h - q * (2^{255} - 19) + 19 * 2^{-255} * (h - q * (2^{255} - 19)) + 1/2 - 19^2 * 2^{-255} * q - 19 * 2^{-255} * (h - 2^{230} * h_9) \\
* &amp;= h - q * 2^{255} + 19 * q + 19 * 2^{-255} * h - 19 * q + 19^2 * 2^{-255} * q + 1/2 - 19^2 * 2^{-255} * q - 19 * 2^{-255} * h + 19 * 2^{-25} * h_9 \\
* &amp;= h + 19 * 2^{-25} * h_9 + 1/2 - q^{255}.
* \end{align}
* $$
* <p>
* Inserting the expression for $x$ into $(1)$ we get the desired expression for $q$.
*/
public byte[] encode(FieldElement x) {
int[] h = ((Ed25519FieldElement)x).t;
@ -150,10 +181,10 @@ public class Ed25519LittleEndianEncoding extends Encoding {
}
/**
* Decodes a given field element in its 10 byte 2^25.5 representation.
* Decodes a given field element in its 10 byte $2^{25.5}$ representation.
*
* @param in The 32 byte representation.
* @return The field element in its 2^25.5 bit representation.
* @return The field element in its $2^{25.5}$ bit representation.
*/
public FieldElement decode(byte[] in) {
long h0 = load_4(in, 0);
@ -207,15 +238,15 @@ public class Ed25519LittleEndianEncoding extends Encoding {
/**
* Is the FieldElement negative in this encoding?
* <p>
* Return true if x is in {1,3,5,...,q-2}<br>
* Return false if x is in {0,2,4,...,q-1}
* Return true if $x$ is in $\{1,3,5,\dots,q-2\}$<br>
* Return false if $x$ is in $\{0,2,4,\dots,q-1\}$
* <p>
* Preconditions:
* </p><ul>
* <li>|x| bounded by 1.1*2^26,1.1*2^25,1.1*2^26,1.1*2^25,etc.
* <li>$|x|$ bounded by $1.1*2^{26},1.1*2^{25},1.1*2^{26},1.1*2^{25}$, etc.
* </ul>
*
* @return true if x is in {1,3,5,...,q-2}, false otherwise.
* @return true if $x$ is in $\{1,3,5,\dots,q-2\}$, false otherwise.
*/
public boolean isNegative(FieldElement x) {
byte[] s = encode(x);

View File

@ -1,3 +1,14 @@
/**
* EdDSA-Java by str4d
*
* To the extent possible under law, the person who associated CC0 with
* EdDSA-Java has waived all copyright and related or neighboring rights
* to EdDSA-Java.
*
* You should have received a copy of the CC0 legalcode along with this
* work. If not, see <https://creativecommons.org/publicdomain/zero/1.0/>.
*
*/
package net.i2p.crypto.eddsa.math.ed25519;
import net.i2p.crypto.eddsa.math.ScalarOps;
@ -8,21 +19,21 @@ import static net.i2p.crypto.eddsa.math.ed25519.Ed25519LittleEndianEncoding.load
* Class for reducing a huge integer modulo the group order q and
* doing a combined multiply plus add plus reduce operation.
* <p>
* q = 2^252 + 27742317777372353535851937790883648493.
* $q = 2^{252} + 27742317777372353535851937790883648493$.
* <p>
* Reviewed/commented by Bloody Rookie (nemproject@gmx.de)
*/
public class Ed25519ScalarOps implements ScalarOps {
/**
* Reduction modulo the group order q.
* Reduction modulo the group order $q$.
* <p>
* Input:
* s[0]+256*s[1]+...+256^63*s[63] = s
* $s[0]+256*s[1]+\dots+256^{63}*s[63] = s$
* <p>
* Output:
* s[0]+256*s[1]+...+256^31*s[31] = s mod q
* where q = 2^252 + 27742317777372353535851937790883648493.
* $s[0]+256*s[1]+\dots+256^{31}*s[31] = s \bmod q$
* where $q = 2^{252} + 27742317777372353535851937790883648493$.
*/
public byte[] reduce(byte[] s) {
// s0,..., s22 have 21 bits, s23 has 29 bits
@ -313,15 +324,17 @@ public class Ed25519ScalarOps implements ScalarOps {
/**
* $(ab+c) \bmod q$
* <p>
* Input:
* <p><ul>
* <li>a[0]+256*a[1]+...+256^31*a[31] = a
* <li>b[0]+256*b[1]+...+256^31*b[31] = b
* <li>c[0]+256*c[1]+...+256^31*c[31] = c
* </p><ul>
* <li>$a[0]+256*a[1]+\dots+256^{31}*a[31] = a$
* <li>$b[0]+256*b[1]+\dots+256^{31}*b[31] = b$
* <li>$c[0]+256*c[1]+\dots+256^{31}*c[31] = c$
* </ul><p>
* Output:
* result[0]+256*result[1]+...+256^31*result[31] = (ab+c) mod q
* where q = 2^252 + 27742317777372353535851937790883648493.
* $result[0]+256*result[1]+\dots+256^{31}*result[31] = (ab+c) \bmod q$
* where $q = 2^{252} + 27742317777372353535851937790883648493$.
* <p>
* See the comments in {@link #reduce(byte[])} for an explanation of the algorithm.
*/

View File

@ -1,6 +1,6 @@
<html><body>
<p>
Low-level, optimized implementation using Radix 2^51 for Curve 25519.
Low-level, optimized implementation using Radix $2^{51}$ for Curve 25519.
See the <a href="../bigint/package-summary.html">bigint</a> implementation for other curves.
</p>
</body></html>

View File

@ -4,6 +4,6 @@
the mathematical operaions on them.
</p><p>
Low-level implementation is in <a href="bigint/package-summary.html">bigint</a> for any curve using BigIntegers,
and in <a href="ed25519/package-summary.html">ed25519</a> for Curve 25519 using Radix 2^51.
and in <a href="ed25519/package-summary.html">ed25519</a> for Curve 25519 using Radix $2^{51}$.
</p>
</body></html>

View File

@ -1,3 +1,14 @@
/**
* EdDSA-Java by str4d
*
* To the extent possible under law, the person who associated CC0 with
* EdDSA-Java has waived all copyright and related or neighboring rights
* to EdDSA-Java.
*
* You should have received a copy of the CC0 legalcode along with this
* work. If not, see <https://creativecommons.org/publicdomain/zero/1.0/>.
*
*/
package net.i2p.crypto.eddsa.spec;
import java.security.spec.AlgorithmParameterSpec;

View File

@ -1,3 +1,14 @@
/**
* EdDSA-Java by str4d
*
* To the extent possible under law, the person who associated CC0 with
* EdDSA-Java has waived all copyright and related or neighboring rights
* to EdDSA-Java.
*
* You should have received a copy of the CC0 legalcode along with this
* work. If not, see <https://creativecommons.org/publicdomain/zero/1.0/>.
*
*/
package net.i2p.crypto.eddsa.spec;
import net.i2p.crypto.eddsa.math.Curve;

View File

@ -1,3 +1,14 @@
/**
* EdDSA-Java by str4d
*
* To the extent possible under law, the person who associated CC0 with
* EdDSA-Java has waived all copyright and related or neighboring rights
* to EdDSA-Java.
*
* You should have received a copy of the CC0 legalcode along with this
* work. If not, see <https://creativecommons.org/publicdomain/zero/1.0/>.
*
*/
package net.i2p.crypto.eddsa.spec;
import java.util.HashMap;

View File

@ -1,3 +1,14 @@
/**
* EdDSA-Java by str4d
*
* To the extent possible under law, the person who associated CC0 with
* EdDSA-Java has waived all copyright and related or neighboring rights
* to EdDSA-Java.
*
* You should have received a copy of the CC0 legalcode along with this
* work. If not, see <https://creativecommons.org/publicdomain/zero/1.0/>.
*
*/
package net.i2p.crypto.eddsa.spec;
import java.security.MessageDigest;
@ -25,11 +36,11 @@ public class EdDSAParameterSpec implements AlgorithmParameterSpec, Serializable
private final GroupElement B;
/**
* @param curve the curve
* @param hashAlgo the JCA string for the hash algorithm
* @param sc the parameter L represented as ScalarOps
* @param B the parameter B
* @throws IllegalArgumentException if hash algorithm is unsupported or length is wrong
* @param curve the curve
* @param hashAlgo the JCA string for the hash algorithm
* @param sc the parameter L represented as ScalarOps
* @param B the parameter B
* @throws IllegalArgumentException if hash algorithm is unsupported or length is wrong
*/
public EdDSAParameterSpec(Curve curve, String hashAlgo,
ScalarOps sc, GroupElement B) {

View File

@ -1,3 +1,14 @@
/**
* EdDSA-Java by str4d
*
* To the extent possible under law, the person who associated CC0 with
* EdDSA-Java has waived all copyright and related or neighboring rights
* to EdDSA-Java.
*
* You should have received a copy of the CC0 legalcode along with this
* work. If not, see <https://creativecommons.org/publicdomain/zero/1.0/>.
*
*/
package net.i2p.crypto.eddsa.spec;
import java.security.MessageDigest;

View File

@ -1,3 +1,14 @@
/**
* EdDSA-Java by str4d
*
* To the extent possible under law, the person who associated CC0 with
* EdDSA-Java has waived all copyright and related or neighboring rights
* to EdDSA-Java.
*
* You should have received a copy of the CC0 legalcode along with this
* work. If not, see <https://creativecommons.org/publicdomain/zero/1.0/>.
*
*/
package net.i2p.crypto.eddsa.spec;
import java.security.spec.KeySpec;
@ -12,13 +23,13 @@ import net.i2p.crypto.eddsa.math.GroupElement;
*/
public class EdDSAPublicKeySpec implements KeySpec {
private final GroupElement A;
private GroupElement Aneg;
private GroupElement Aneg = null;
private final EdDSAParameterSpec spec;
/**
* @param pk the public key
* @param spec the parameter specification for this key
* @throws IllegalArgumentException if key length is wrong
* @param pk the public key
* @param spec the parameter specification for this key
* @throws IllegalArgumentException if key length is wrong
*/
public EdDSAPublicKeySpec(byte[] pk, EdDSAParameterSpec spec) {
if (pk.length != spec.getCurve().getField().getb()/8)

View File

@ -1,3 +1,14 @@
/**
* EdDSA-Java by str4d
*
* To the extent possible under law, the person who associated CC0 with
* EdDSA-Java has waived all copyright and related or neighboring rights
* to EdDSA-Java.
*
* You should have received a copy of the CC0 legalcode along with this
* work. If not, see <https://creativecommons.org/publicdomain/zero/1.0/>.
*
*/
package net.i2p.crypto.eddsa;
import java.io.BufferedReader;

View File

@ -1,3 +1,14 @@
/**
* EdDSA-Java by str4d
*
* To the extent possible under law, the person who associated CC0 with
* EdDSA-Java has waived all copyright and related or neighboring rights
* to EdDSA-Java.
*
* You should have received a copy of the CC0 legalcode along with this
* work. If not, see <https://creativecommons.org/publicdomain/zero/1.0/>.
*
*/
package net.i2p.crypto.eddsa;
import static org.hamcrest.Matchers.equalTo;

View File

@ -1,3 +1,14 @@
/**
* EdDSA-Java by str4d
*
* To the extent possible under law, the person who associated CC0 with
* EdDSA-Java has waived all copyright and related or neighboring rights
* to EdDSA-Java.
*
* You should have received a copy of the CC0 legalcode along with this
* work. If not, see <https://creativecommons.org/publicdomain/zero/1.0/>.
*
*/
package net.i2p.crypto.eddsa;
import org.hamcrest.core.IsEqual;
@ -105,6 +116,11 @@ public class UtilsTest {
assertThat(Utils.bit(new byte[] {1, 2, 3}, 16), is(1));
}
@Test(expected = IllegalArgumentException.class)
public void hexToBytesThrowsOnInvalidLengthHexString() {
Utils.hexToBytes("bad");
}
@Test
public void hexToBytesReturnsCorrectByteArray() {
Assert.assertThat(Utils.hexToBytes(hex1), IsEqual.equalTo(bytes1));

View File

@ -1,6 +1,16 @@
/**
* EdDSA-Java by str4d
*
* To the extent possible under law, the person who associated CC0 with
* EdDSA-Java has waived all copyright and related or neighboring rights
* to EdDSA-Java.
*
* You should have received a copy of the CC0 legalcode along with this
* work. If not, see <https://creativecommons.org/publicdomain/zero/1.0/>.
*
*/
package net.i2p.crypto.eddsa.math;
import net.i2p.crypto.eddsa.math.*;
import org.hamcrest.core.*;
import org.junit.*;

View File

@ -1,3 +1,14 @@
/**
* EdDSA-Java by str4d
*
* To the extent possible under law, the person who associated CC0 with
* EdDSA-Java has waived all copyright and related or neighboring rights
* to EdDSA-Java.
*
* You should have received a copy of the CC0 legalcode along with this
* work. If not, see <https://creativecommons.org/publicdomain/zero/1.0/>.
*
*/
package net.i2p.crypto.eddsa.math;
import static org.hamcrest.Matchers.equalTo;

View File

@ -1,3 +1,14 @@
/**
* EdDSA-Java by str4d
*
* To the extent possible under law, the person who associated CC0 with
* EdDSA-Java has waived all copyright and related or neighboring rights
* to EdDSA-Java.
*
* You should have received a copy of the CC0 legalcode along with this
* work. If not, see <https://creativecommons.org/publicdomain/zero/1.0/>.
*
*/
package net.i2p.crypto.eddsa.math;
import net.i2p.crypto.eddsa.*;

View File

@ -1,3 +1,14 @@
/**
* EdDSA-Java by str4d
*
* To the extent possible under law, the person who associated CC0 with
* EdDSA-Java has waived all copyright and related or neighboring rights
* to EdDSA-Java.
*
* You should have received a copy of the CC0 legalcode along with this
* work. If not, see <https://creativecommons.org/publicdomain/zero/1.0/>.
*
*/
package net.i2p.crypto.eddsa.math;
import net.i2p.crypto.eddsa.Utils;

View File

@ -1,3 +1,14 @@
/**
* EdDSA-Java by str4d
*
* To the extent possible under law, the person who associated CC0 with
* EdDSA-Java has waived all copyright and related or neighboring rights
* to EdDSA-Java.
*
* You should have received a copy of the CC0 legalcode along with this
* work. If not, see <https://creativecommons.org/publicdomain/zero/1.0/>.
*
*/
package net.i2p.crypto.eddsa.math;
import java.io.BufferedReader;

View File

@ -1,3 +1,14 @@
/**
* EdDSA-Java by str4d
*
* To the extent possible under law, the person who associated CC0 with
* EdDSA-Java has waived all copyright and related or neighboring rights
* to EdDSA-Java.
*
* You should have received a copy of the CC0 legalcode along with this
* work. If not, see <https://creativecommons.org/publicdomain/zero/1.0/>.
*
*/
package net.i2p.crypto.eddsa.math.bigint;
import static org.hamcrest.Matchers.*;

View File

@ -1,5 +1,13 @@
/**
*
* EdDSA-Java by str4d
*
* To the extent possible under law, the person who associated CC0 with
* EdDSA-Java has waived all copyright and related or neighboring rights
* to EdDSA-Java.
*
* You should have received a copy of the CC0 legalcode along with this
* work. If not, see <https://creativecommons.org/publicdomain/zero/1.0/>.
*
*/
package net.i2p.crypto.eddsa.math.bigint;

View File

@ -1,3 +1,14 @@
/**
* EdDSA-Java by str4d
*
* To the extent possible under law, the person who associated CC0 with
* EdDSA-Java has waived all copyright and related or neighboring rights
* to EdDSA-Java.
*
* You should have received a copy of the CC0 legalcode along with this
* work. If not, see <https://creativecommons.org/publicdomain/zero/1.0/>.
*
*/
package net.i2p.crypto.eddsa.math.ed25519;
import net.i2p.crypto.eddsa.math.*;

View File

@ -1,3 +1,14 @@
/**
* EdDSA-Java by str4d
*
* To the extent possible under law, the person who associated CC0 with
* EdDSA-Java has waived all copyright and related or neighboring rights
* to EdDSA-Java.
*
* You should have received a copy of the CC0 legalcode along with this
* work. If not, see <https://creativecommons.org/publicdomain/zero/1.0/>.
*
*/
package net.i2p.crypto.eddsa.math.ed25519;
import net.i2p.crypto.eddsa.math.*;

View File

@ -1,5 +1,13 @@
/**
*
* EdDSA-Java by str4d
*
* To the extent possible under law, the person who associated CC0 with
* EdDSA-Java has waived all copyright and related or neighboring rights
* to EdDSA-Java.
*
* You should have received a copy of the CC0 legalcode along with this
* work. If not, see <https://creativecommons.org/publicdomain/zero/1.0/>.
*
*/
package net.i2p.crypto.eddsa.math.ed25519;

View File

@ -1,3 +1,14 @@
/**
* EdDSA-Java by str4d
*
* To the extent possible under law, the person who associated CC0 with
* EdDSA-Java has waived all copyright and related or neighboring rights
* to EdDSA-Java.
*
* You should have received a copy of the CC0 legalcode along with this
* work. If not, see <https://creativecommons.org/publicdomain/zero/1.0/>.
*
*/
package net.i2p.crypto.eddsa.spec;
import static org.hamcrest.Matchers.*;
@ -38,7 +49,7 @@ public class EdDSAPrivateKeySpecTest {
public void incorrectSeedLengthThrows() {
exception.expect(IllegalArgumentException.class);
exception.expectMessage("seed length is wrong");
EdDSAPrivateKeySpec key = new EdDSAPrivateKeySpec(new byte[2], ed25519);
new EdDSAPrivateKeySpec(new byte[2], ed25519);
}
/**
@ -56,6 +67,6 @@ public class EdDSAPrivateKeySpecTest {
public void incorrectHashLengthThrows() {
exception.expect(IllegalArgumentException.class);
exception.expectMessage("hash length is wrong");
EdDSAPrivateKeySpec key = new EdDSAPrivateKeySpec(ed25519, new byte[2]);
new EdDSAPrivateKeySpec(ed25519, new byte[2]);
}
}