edParameters;
39 |
40 | static {
41 | edParameters = new Hashtable();
42 |
43 | edParameters.put(Integer.valueOf(256), new EdDSAGenParameterSpec(EdDSANamedCurveTable.ED_25519));
44 | }
45 |
46 | public void initialize(int keysize, SecureRandom random) {
47 | AlgorithmParameterSpec edParams = edParameters.get(Integer.valueOf(keysize));
48 | if (edParams == null)
49 | throw new InvalidParameterException("unknown key type.");
50 | try {
51 | initialize(edParams, random);
52 | } catch (InvalidAlgorithmParameterException e) {
53 | throw new InvalidParameterException("key type not configurable.");
54 | }
55 | }
56 |
57 | @Override
58 | public void initialize(AlgorithmParameterSpec params, SecureRandom random) throws InvalidAlgorithmParameterException {
59 | if (params instanceof EdDSAParameterSpec) {
60 | edParams = (EdDSAParameterSpec) params;
61 | } else if (params instanceof EdDSAGenParameterSpec) {
62 | edParams = createNamedCurveSpec(((EdDSAGenParameterSpec) params).getName());
63 | } else
64 | throw new InvalidAlgorithmParameterException("parameter object not a EdDSAParameterSpec");
65 |
66 | this.random = random;
67 | initialized = true;
68 | }
69 |
70 | public KeyPair generateKeyPair() {
71 | if (!initialized)
72 | initialize(DEFAULT_KEYSIZE, new SecureRandom());
73 |
74 | byte[] seed = new byte[edParams.getCurve().getField().getb()/8];
75 | random.nextBytes(seed);
76 |
77 | EdDSAPrivateKeySpec privKey = new EdDSAPrivateKeySpec(seed, edParams);
78 | EdDSAPublicKeySpec pubKey = new EdDSAPublicKeySpec(privKey.getA(), edParams);
79 |
80 | return new KeyPair(new EdDSAPublicKey(pubKey), new EdDSAPrivateKey(privKey));
81 | }
82 |
83 | /**
84 | * Create an EdDSANamedCurveSpec from the provided curve name. The current
85 | * implementation fetches the pre-created curve spec from a table.
86 | * @param curveName the EdDSA named curve.
87 | * @return the specification for the named curve.
88 | * @throws InvalidAlgorithmParameterException if the named curve is unknown.
89 | */
90 | protected EdDSANamedCurveSpec createNamedCurveSpec(String curveName) throws InvalidAlgorithmParameterException {
91 | EdDSANamedCurveSpec spec = EdDSANamedCurveTable.getByName(curveName);
92 | if (spec == null) {
93 | throw new InvalidAlgorithmParameterException("unknown curve name: " + curveName);
94 | }
95 | return spec;
96 | }
97 | }
98 |
--------------------------------------------------------------------------------
/ext/ed25519_jruby/net/i2p/crypto/eddsa/Utils.java:
--------------------------------------------------------------------------------
1 | /**
2 | * EdDSA-Java by str4d
3 | *
4 | * To the extent possible under law, the person who associated CC0 with
5 | * EdDSA-Java has waived all copyright and related or neighboring rights
6 | * to EdDSA-Java.
7 | *
8 | * You should have received a copy of the CC0 legalcode along with this
9 | * work. If not, see .
10 | *
11 | */
12 | package net.i2p.crypto.eddsa;
13 |
14 | /**
15 | * Basic utilities for EdDSA.
16 | * Not for external use, not maintained as a public API.
17 | *
18 | * @author str4d
19 | *
20 | */
21 | public class Utils {
22 | /**
23 | * Constant-time byte comparison.
24 | * @param b a byte
25 | * @param c a byte
26 | * @return 1 if b and c are equal, 0 otherwise.
27 | */
28 | public static int equal(int b, int c) {
29 | int result = 0;
30 | int xor = b ^ c;
31 | for (int i = 0; i < 8; i++) {
32 | result |= xor >> i;
33 | }
34 | return (result ^ 0x01) & 0x01;
35 | }
36 |
37 | /**
38 | * Constant-time byte[] comparison.
39 | * @param b a byte[]
40 | * @param c a byte[]
41 | * @return 1 if b and c are equal, 0 otherwise.
42 | */
43 | public static int equal(byte[] b, byte[] c) {
44 | int result = 0;
45 | for (int i = 0; i < 32; i++) {
46 | result |= b[i] ^ c[i];
47 | }
48 |
49 | return equal(result, 0);
50 | }
51 |
52 | /**
53 | * Constant-time determine if byte is negative.
54 | * @param b the byte to check.
55 | * @return 1 if the byte is negative, 0 otherwise.
56 | */
57 | public static int negative(int b) {
58 | return (b >> 8) & 1;
59 | }
60 |
61 | /**
62 | * Get the i'th bit of a byte array.
63 | * @param h the byte array.
64 | * @param i the bit index.
65 | * @return 0 or 1, the value of the i'th bit in h
66 | */
67 | public static int bit(byte[] h, int i) {
68 | return (h[i >> 3] >> (i & 7)) & 1;
69 | }
70 |
71 | /**
72 | * Converts a hex string to bytes.
73 | * @param s the hex string to be converted.
74 | * @return the byte[]
75 | */
76 | public static byte[] hexToBytes(String s) {
77 | int len = s.length();
78 | byte[] data = new byte[len / 2];
79 | for (int i = 0; i < len; i += 2) {
80 | data[i / 2] = (byte) ((Character.digit(s.charAt(i), 16) << 4)
81 | + Character.digit(s.charAt(i+1), 16));
82 | }
83 | return data;
84 | }
85 |
86 | /**
87 | * Converts bytes to a hex string.
88 | * @param raw the byte[] to be converted.
89 | * @return the hex representation as a string.
90 | */
91 | public static String bytesToHex(byte[] raw) {
92 | if ( raw == null ) {
93 | return null;
94 | }
95 | final StringBuilder hex = new StringBuilder(2 * raw.length);
96 | for (final byte b : raw) {
97 | hex.append(Character.forDigit((b & 0xF0) >> 4, 16))
98 | .append(Character.forDigit((b & 0x0F), 16));
99 | }
100 | return hex.toString();
101 | }
102 |
103 | }
104 |
--------------------------------------------------------------------------------
/ext/ed25519_jruby/net/i2p/crypto/eddsa/math/Constants.java:
--------------------------------------------------------------------------------
1 | /**
2 | * EdDSA-Java by str4d
3 | *
4 | * To the extent possible under law, the person who associated CC0 with
5 | * EdDSA-Java has waived all copyright and related or neighboring rights
6 | * to EdDSA-Java.
7 | *
8 | * You should have received a copy of the CC0 legalcode along with this
9 | * work. If not, see .
10 | *
11 | */
12 | package net.i2p.crypto.eddsa.math;
13 |
14 | import net.i2p.crypto.eddsa.Utils;
15 |
16 | final class Constants {
17 | public static final byte[] ZERO = Utils.hexToBytes("0000000000000000000000000000000000000000000000000000000000000000");
18 | public static final byte[] ONE = Utils.hexToBytes("0100000000000000000000000000000000000000000000000000000000000000");
19 | public static final byte[] TWO = Utils.hexToBytes("0200000000000000000000000000000000000000000000000000000000000000");
20 | public static final byte[] FOUR = Utils.hexToBytes("0400000000000000000000000000000000000000000000000000000000000000");
21 | public static final byte[] FIVE = Utils.hexToBytes("0500000000000000000000000000000000000000000000000000000000000000");
22 | public static final byte[] EIGHT = Utils.hexToBytes("0800000000000000000000000000000000000000000000000000000000000000");
23 | }
24 |
--------------------------------------------------------------------------------
/ext/ed25519_jruby/net/i2p/crypto/eddsa/math/Curve.java:
--------------------------------------------------------------------------------
1 | /**
2 | * EdDSA-Java by str4d
3 | *
4 | * To the extent possible under law, the person who associated CC0 with
5 | * EdDSA-Java has waived all copyright and related or neighboring rights
6 | * to EdDSA-Java.
7 | *
8 | * You should have received a copy of the CC0 legalcode along with this
9 | * work. If not, see .
10 | *
11 | */
12 | package net.i2p.crypto.eddsa.math;
13 |
14 | import java.io.Serializable;
15 |
16 | /**
17 | * A twisted Edwards curve.
18 | * Points on the curve satisfy $-x^2 + y^2 = 1 + d x^2y^2$
19 | * @author str4d
20 | *
21 | */
22 | public class Curve implements Serializable {
23 | private static final long serialVersionUID = 4578920872509827L;
24 | private final Field f;
25 | private final FieldElement d;
26 | private final FieldElement d2;
27 | private final FieldElement I;
28 |
29 | private final GroupElement zeroP2;
30 | private final GroupElement zeroP3;
31 | private final GroupElement zeroPrecomp;
32 |
33 | public Curve(Field f, byte[] d, FieldElement I) {
34 | this.f = f;
35 | this.d = f.fromByteArray(d);
36 | this.d2 = this.d.add(this.d);
37 | this.I = I;
38 |
39 | FieldElement zero = f.ZERO;
40 | FieldElement one = f.ONE;
41 | zeroP2 = GroupElement.p2(this, zero, one, one);
42 | zeroP3 = GroupElement.p3(this, zero, one, one, zero);
43 | zeroPrecomp = GroupElement.precomp(this, one, one, zero);
44 | }
45 |
46 | public Field getField() {
47 | return f;
48 | }
49 |
50 | public FieldElement getD() {
51 | return d;
52 | }
53 |
54 | public FieldElement get2D() {
55 | return d2;
56 | }
57 |
58 | public FieldElement getI() {
59 | return I;
60 | }
61 |
62 | public GroupElement getZero(GroupElement.Representation repr) {
63 | switch (repr) {
64 | case P2:
65 | return zeroP2;
66 | case P3:
67 | return zeroP3;
68 | case PRECOMP:
69 | return zeroPrecomp;
70 | default:
71 | return null;
72 | }
73 | }
74 |
75 | public GroupElement createPoint(byte[] P, boolean precompute) {
76 | GroupElement ge = new GroupElement(this, P);
77 | if (precompute)
78 | ge.precompute(true);
79 | return ge;
80 | }
81 |
82 | @Override
83 | public int hashCode() {
84 | return f.hashCode() ^
85 | d.hashCode() ^
86 | I.hashCode();
87 | }
88 |
89 | @Override
90 | public boolean equals(Object o) {
91 | if (o == this)
92 | return true;
93 | if (!(o instanceof Curve))
94 | return false;
95 | Curve c = (Curve) o;
96 | return f.equals(c.getField()) &&
97 | d.equals(c.getD()) &&
98 | I.equals(c.getI());
99 | }
100 | }
101 |
--------------------------------------------------------------------------------
/ext/ed25519_jruby/net/i2p/crypto/eddsa/math/Encoding.java:
--------------------------------------------------------------------------------
1 | /**
2 | * EdDSA-Java by str4d
3 | *
4 | * To the extent possible under law, the person who associated CC0 with
5 | * EdDSA-Java has waived all copyright and related or neighboring rights
6 | * to EdDSA-Java.
7 | *
8 | * You should have received a copy of the CC0 legalcode along with this
9 | * work. If not, see .
10 | *
11 | */
12 | package net.i2p.crypto.eddsa.math;
13 |
14 | /**
15 | * Common interface for all $(b-1)$-bit encodings of elements
16 | * of EdDSA finite fields.
17 | * @author str4d
18 | *
19 | */
20 | public abstract class Encoding {
21 | protected Field f;
22 |
23 | public synchronized void setField(Field f) {
24 | if (this.f != null)
25 | throw new IllegalStateException("already set");
26 | this.f = f;
27 | }
28 |
29 | /**
30 | * Encode a FieldElement in its $(b-1)$-bit encoding.
31 | * @param x the FieldElement to encode
32 | * @return the $(b-1)$-bit encoding of this FieldElement.
33 | */
34 | public abstract byte[] encode(FieldElement x);
35 |
36 | /**
37 | * Decode a FieldElement from its $(b-1)$-bit encoding.
38 | * The highest bit is masked out.
39 | * @param in the $(b-1)$-bit encoding of a FieldElement.
40 | * @return the FieldElement represented by 'val'.
41 | */
42 | public abstract FieldElement decode(byte[] in);
43 |
44 | /**
45 | * From the Ed25519 paper:
46 | * $x$ is negative if the $(b-1)$-bit encoding of $x$ is lexicographically larger
47 | * than the $(b-1)$-bit encoding of -x. If $q$ is an odd prime and the encoding
48 | * is the little-endian representation of $\{0, 1,\dots, q-1\}$ then the negative
49 | * elements of $F_q$ are $\{1, 3, 5,\dots, q-2\}$.
50 | * @param x the FieldElement to check
51 | * @return true if negative
52 | */
53 | public abstract boolean isNegative(FieldElement x);
54 | }
55 |
--------------------------------------------------------------------------------
/ext/ed25519_jruby/net/i2p/crypto/eddsa/math/Field.java:
--------------------------------------------------------------------------------
1 | /**
2 | * EdDSA-Java by str4d
3 | *
4 | * To the extent possible under law, the person who associated CC0 with
5 | * EdDSA-Java has waived all copyright and related or neighboring rights
6 | * to EdDSA-Java.
7 | *
8 | * You should have received a copy of the CC0 legalcode along with this
9 | * work. If not, see .
10 | *
11 | */
12 | package net.i2p.crypto.eddsa.math;
13 |
14 | import java.io.Serializable;
15 |
16 | /**
17 | * An EdDSA finite field. Includes several pre-computed values.
18 | * @author str4d
19 | *
20 | */
21 | public class Field implements Serializable {
22 | private static final long serialVersionUID = 8746587465875676L;
23 |
24 | public final FieldElement ZERO;
25 | public final FieldElement ONE;
26 | public final FieldElement TWO;
27 | public final FieldElement FOUR;
28 | public final FieldElement FIVE;
29 | public final FieldElement EIGHT;
30 |
31 | private final int b;
32 | private final FieldElement q;
33 | /**
34 | * q-2
35 | */
36 | private final FieldElement qm2;
37 | /**
38 | * (q-5) / 8
39 | */
40 | private final FieldElement qm5d8;
41 | private final Encoding enc;
42 |
43 | public Field(int b, byte[] q, Encoding enc) {
44 | this.b = b;
45 | this.enc = enc;
46 | this.enc.setField(this);
47 |
48 | this.q = fromByteArray(q);
49 |
50 | // Set up constants
51 | ZERO = fromByteArray(Constants.ZERO);
52 | ONE = fromByteArray(Constants.ONE);
53 | TWO = fromByteArray(Constants.TWO);
54 | FOUR = fromByteArray(Constants.FOUR);
55 | FIVE = fromByteArray(Constants.FIVE);
56 | EIGHT = fromByteArray(Constants.EIGHT);
57 |
58 | // Precompute values
59 | qm2 = this.q.subtract(TWO);
60 | qm5d8 = this.q.subtract(FIVE).divide(EIGHT);
61 | }
62 |
63 | public FieldElement fromByteArray(byte[] x) {
64 | return enc.decode(x);
65 | }
66 |
67 | public int getb() {
68 | return b;
69 | }
70 |
71 | public FieldElement getQ() {
72 | return q;
73 | }
74 |
75 | public FieldElement getQm2() {
76 | return qm2;
77 | }
78 |
79 | public FieldElement getQm5d8() {
80 | return qm5d8;
81 | }
82 |
83 | public Encoding getEncoding(){
84 | return enc;
85 | }
86 |
87 | @Override
88 | public int hashCode() {
89 | return q.hashCode();
90 | }
91 |
92 | @Override
93 | public boolean equals(Object obj) {
94 | if (!(obj instanceof Field))
95 | return false;
96 | Field f = (Field) obj;
97 | return b == f.b && q.equals(f.q);
98 | }
99 | }
100 |
--------------------------------------------------------------------------------
/ext/ed25519_jruby/net/i2p/crypto/eddsa/math/FieldElement.java:
--------------------------------------------------------------------------------
1 | /**
2 | * EdDSA-Java by str4d
3 | *
4 | * To the extent possible under law, the person who associated CC0 with
5 | * EdDSA-Java has waived all copyright and related or neighboring rights
6 | * to EdDSA-Java.
7 | *
8 | * You should have received a copy of the CC0 legalcode along with this
9 | * work. If not, see .
10 | *
11 | */
12 | package net.i2p.crypto.eddsa.math;
13 |
14 | import java.io.Serializable;
15 |
16 | /**
17 | * Note: concrete subclasses must implement hashCode() and equals()
18 | */
19 | public abstract class FieldElement implements Serializable {
20 | private static final long serialVersionUID = 1239527465875676L;
21 |
22 | protected final Field f;
23 |
24 | public FieldElement(Field f) {
25 | if (null == f) {
26 | throw new IllegalArgumentException("field cannot be null");
27 | }
28 | this.f = f;
29 | }
30 |
31 | /**
32 | * Encode a FieldElement in its $(b-1)$-bit encoding.
33 | * @return the $(b-1)$-bit encoding of this FieldElement.
34 | */
35 | public byte[] toByteArray() {
36 | return f.getEncoding().encode(this);
37 | }
38 |
39 | public abstract boolean isNonZero();
40 |
41 | public boolean isNegative() {
42 | return f.getEncoding().isNegative(this);
43 | }
44 |
45 | public abstract FieldElement add(FieldElement val);
46 |
47 | public FieldElement addOne() {
48 | return add(f.ONE);
49 | }
50 |
51 | public abstract FieldElement subtract(FieldElement val);
52 |
53 | public FieldElement subtractOne() {
54 | return subtract(f.ONE);
55 | }
56 |
57 | public abstract FieldElement negate();
58 |
59 | public FieldElement divide(FieldElement val) {
60 | return multiply(val.invert());
61 | }
62 |
63 | public abstract FieldElement multiply(FieldElement val);
64 |
65 | public abstract FieldElement square();
66 |
67 | public abstract FieldElement squareAndDouble();
68 |
69 | public abstract FieldElement invert();
70 |
71 | public abstract FieldElement pow22523();
72 |
73 | public abstract FieldElement cmov(FieldElement val, final int b);
74 |
75 | // Note: concrete subclasses must implement hashCode() and equals()
76 | }
77 |
--------------------------------------------------------------------------------
/ext/ed25519_jruby/net/i2p/crypto/eddsa/math/ScalarOps.java:
--------------------------------------------------------------------------------
1 | /**
2 | * EdDSA-Java by str4d
3 | *
4 | * To the extent possible under law, the person who associated CC0 with
5 | * EdDSA-Java has waived all copyright and related or neighboring rights
6 | * to EdDSA-Java.
7 | *
8 | * You should have received a copy of the CC0 legalcode along with this
9 | * work. If not, see .
10 | *
11 | */
12 | package net.i2p.crypto.eddsa.math;
13 |
14 | public interface ScalarOps {
15 | /**
16 | * Reduce the given scalar mod $l$.
17 | *
18 | * From the Ed25519 paper:
19 | * Here we interpret $2b$-bit strings in little-endian form as integers in
20 | * $\{0, 1,..., 2^{(2b)}-1\}$.
21 | * @param s the scalar to reduce
22 | * @return $s \bmod l$
23 | */
24 | public byte[] reduce(byte[] s);
25 |
26 | /**
27 | * $r = (a * b + c) \bmod l$
28 | * @param a a scalar
29 | * @param b a scalar
30 | * @param c a scalar
31 | * @return $(a*b + c) \bmod l$
32 | */
33 | public byte[] multiplyAndAdd(byte[] a, byte[] b, byte[] c);
34 | }
35 |
--------------------------------------------------------------------------------
/ext/ed25519_jruby/net/i2p/crypto/eddsa/math/bigint/BigIntegerFieldElement.java:
--------------------------------------------------------------------------------
1 | /**
2 | * EdDSA-Java by str4d
3 | *
4 | * To the extent possible under law, the person who associated CC0 with
5 | * EdDSA-Java has waived all copyright and related or neighboring rights
6 | * to EdDSA-Java.
7 | *
8 | * You should have received a copy of the CC0 legalcode along with this
9 | * work. If not, see .
10 | *
11 | */
12 | package net.i2p.crypto.eddsa.math.bigint;
13 |
14 | import java.io.Serializable;
15 | import java.math.BigInteger;
16 |
17 | import net.i2p.crypto.eddsa.math.Field;
18 | import net.i2p.crypto.eddsa.math.FieldElement;
19 |
20 | /**
21 | * A particular element of the field \Z/(2^255-19).
22 | * @author str4d
23 | *
24 | */
25 | public class BigIntegerFieldElement extends FieldElement implements Serializable {
26 | private static final long serialVersionUID = 4890398908392808L;
27 | /**
28 | * Variable is package private for encoding.
29 | */
30 | final BigInteger bi;
31 |
32 | public BigIntegerFieldElement(Field f, BigInteger bi) {
33 | super(f);
34 | this.bi = bi;
35 | }
36 |
37 | public boolean isNonZero() {
38 | return !bi.equals(BigInteger.ZERO);
39 | }
40 |
41 | public FieldElement add(FieldElement val) {
42 | return new BigIntegerFieldElement(f, bi.add(((BigIntegerFieldElement)val).bi)).mod(f.getQ());
43 | }
44 |
45 | @Override
46 | public FieldElement addOne() {
47 | return new BigIntegerFieldElement(f, bi.add(BigInteger.ONE)).mod(f.getQ());
48 | }
49 |
50 | public FieldElement subtract(FieldElement val) {
51 | return new BigIntegerFieldElement(f, bi.subtract(((BigIntegerFieldElement)val).bi)).mod(f.getQ());
52 | }
53 |
54 | @Override
55 | public FieldElement subtractOne() {
56 | return new BigIntegerFieldElement(f, bi.subtract(BigInteger.ONE)).mod(f.getQ());
57 | }
58 |
59 | public FieldElement negate() {
60 | return f.getQ().subtract(this);
61 | }
62 |
63 | @Override
64 | public FieldElement divide(FieldElement val) {
65 | return divide(((BigIntegerFieldElement)val).bi);
66 | }
67 |
68 | public FieldElement divide(BigInteger val) {
69 | return new BigIntegerFieldElement(f, bi.divide(val)).mod(f.getQ());
70 | }
71 |
72 | public FieldElement multiply(FieldElement val) {
73 | return new BigIntegerFieldElement(f, bi.multiply(((BigIntegerFieldElement)val).bi)).mod(f.getQ());
74 | }
75 |
76 | public FieldElement square() {
77 | return multiply(this);
78 | }
79 |
80 | public FieldElement squareAndDouble() {
81 | FieldElement sq = square();
82 | return sq.add(sq);
83 | }
84 |
85 | public FieldElement invert() {
86 | // Euler's theorem
87 | //return modPow(f.getQm2(), f.getQ());
88 | return new BigIntegerFieldElement(f, bi.modInverse(((BigIntegerFieldElement)f.getQ()).bi));
89 | }
90 |
91 | public FieldElement mod(FieldElement m) {
92 | return new BigIntegerFieldElement(f, bi.mod(((BigIntegerFieldElement)m).bi));
93 | }
94 |
95 | public FieldElement modPow(FieldElement e, FieldElement m) {
96 | return new BigIntegerFieldElement(f, bi.modPow(((BigIntegerFieldElement)e).bi, ((BigIntegerFieldElement)m).bi));
97 | }
98 |
99 | public FieldElement pow(FieldElement e){
100 | return modPow(e, f.getQ());
101 | }
102 |
103 | public FieldElement pow22523(){
104 | return pow(f.getQm5d8());
105 | }
106 |
107 | @Override
108 | public FieldElement cmov(FieldElement val, int b) {
109 | // Not constant-time, but it doesn't really matter because none of the underlying BigInteger operations
110 | // are either, so there's not much point in trying hard here ...
111 | return b == 0 ? this : val;
112 | }
113 |
114 | @Override
115 | public int hashCode() {
116 | return bi.hashCode();
117 | }
118 |
119 | @Override
120 | public boolean equals(Object obj) {
121 | if (!(obj instanceof BigIntegerFieldElement))
122 | return false;
123 | BigIntegerFieldElement fe = (BigIntegerFieldElement) obj;
124 | return bi.equals(fe.bi);
125 | }
126 |
127 | @Override
128 | public String toString() {
129 | return "[BigIntegerFieldElement val="+bi+"]";
130 | }
131 | }
132 |
--------------------------------------------------------------------------------
/ext/ed25519_jruby/net/i2p/crypto/eddsa/math/bigint/BigIntegerLittleEndianEncoding.java:
--------------------------------------------------------------------------------
1 | /**
2 | * EdDSA-Java by str4d
3 | *
4 | * To the extent possible under law, the person who associated CC0 with
5 | * EdDSA-Java has waived all copyright and related or neighboring rights
6 | * to EdDSA-Java.
7 | *
8 | * You should have received a copy of the CC0 legalcode along with this
9 | * work. If not, see .
10 | *
11 | */
12 | package net.i2p.crypto.eddsa.math.bigint;
13 |
14 | import java.io.Serializable;
15 | import java.math.BigInteger;
16 |
17 | import net.i2p.crypto.eddsa.math.Encoding;
18 | import net.i2p.crypto.eddsa.math.Field;
19 | import net.i2p.crypto.eddsa.math.FieldElement;
20 |
21 | public class BigIntegerLittleEndianEncoding extends Encoding implements Serializable {
22 | private static final long serialVersionUID = 3984579843759837L;
23 | /**
24 | * Mask where only the first b-1 bits are set.
25 | */
26 | private BigInteger mask;
27 |
28 | @Override
29 | public synchronized void setField(Field f) {
30 | super.setField(f);
31 | mask = BigInteger.ONE.shiftLeft(f.getb()-1).subtract(BigInteger.ONE);
32 | }
33 |
34 | public byte[] encode(FieldElement x) {
35 | return encode(((BigIntegerFieldElement)x).bi.and(mask));
36 | }
37 |
38 | /**
39 | * Convert $x$ to little endian.
40 | * Constant time.
41 | *
42 | * @param x the BigInteger value to encode
43 | * @return array of length $b/8$
44 | * @throws IllegalStateException if field not set
45 | */
46 | public byte[] encode(BigInteger x) {
47 | if (f == null)
48 | throw new IllegalStateException("field not set");
49 | byte[] in = x.toByteArray();
50 | byte[] out = new byte[f.getb()/8];
51 | for (int i = 0; i < in.length; i++) {
52 | out[i] = in[in.length-1-i];
53 | }
54 | for (int i = in.length; i < out.length; i++) {
55 | out[i] = 0;
56 | }
57 | return out;
58 | }
59 |
60 | /**
61 | * Decode a FieldElement from its $(b-1)$-bit encoding.
62 | * The highest bit is masked out.
63 | *
64 | * @param in the $(b-1)$-bit encoding of a FieldElement.
65 | * @return the FieldElement represented by 'val'.
66 | * @throws IllegalStateException if field not set
67 | * @throws IllegalArgumentException if encoding is invalid
68 | */
69 | public FieldElement decode(byte[] in) {
70 | if (f == null)
71 | throw new IllegalStateException("field not set");
72 | if (in.length != f.getb()/8)
73 | throw new IllegalArgumentException("Not a valid encoding");
74 | return new BigIntegerFieldElement(f, toBigInteger(in).and(mask));
75 | }
76 |
77 | /**
78 | * Convert in to big endian
79 | *
80 | * @param in the $(b-1)$-bit encoding of a FieldElement.
81 | * @return the decoded value as a BigInteger
82 | */
83 | public BigInteger toBigInteger(byte[] in) {
84 | byte[] out = new byte[in.length];
85 | for (int i = 0; i < in.length; i++) {
86 | out[i] = in[in.length-1-i];
87 | }
88 | return new BigInteger(1, out);
89 | }
90 |
91 | /**
92 | * From the Ed25519 paper:
93 | * $x$ is negative if the $(b-1)$-bit encoding of $x$ is lexicographically larger
94 | * than the $(b-1)$-bit encoding of $-x$. If $q$ is an odd prime and the encoding
95 | * is the little-endian representation of $\{0, 1,\dots, q-1\}$ then the negative
96 | * elements of $F_q$ are $\{1, 3, 5,\dots, q-2\}$.
97 | * @return true if negative
98 | */
99 | public boolean isNegative(FieldElement x) {
100 | return ((BigIntegerFieldElement)x).bi.testBit(0);
101 | }
102 | }
103 |
--------------------------------------------------------------------------------
/ext/ed25519_jruby/net/i2p/crypto/eddsa/math/bigint/BigIntegerScalarOps.java:
--------------------------------------------------------------------------------
1 | /**
2 | * EdDSA-Java by str4d
3 | *
4 | * To the extent possible under law, the person who associated CC0 with
5 | * EdDSA-Java has waived all copyright and related or neighboring rights
6 | * to EdDSA-Java.
7 | *
8 | * You should have received a copy of the CC0 legalcode along with this
9 | * work. If not, see .
10 | *
11 | */
12 | package net.i2p.crypto.eddsa.math.bigint;
13 |
14 | import java.math.BigInteger;
15 |
16 | import net.i2p.crypto.eddsa.math.Field;
17 | import net.i2p.crypto.eddsa.math.ScalarOps;
18 |
19 | public class BigIntegerScalarOps implements ScalarOps {
20 | private final BigInteger l;
21 | private final BigIntegerLittleEndianEncoding enc;
22 |
23 | public BigIntegerScalarOps(Field f, BigInteger l) {
24 | this.l = l;
25 | enc = new BigIntegerLittleEndianEncoding();
26 | enc.setField(f);
27 | }
28 |
29 | public byte[] reduce(byte[] s) {
30 | return enc.encode(enc.toBigInteger(s).mod(l));
31 | }
32 |
33 | public byte[] multiplyAndAdd(byte[] a, byte[] b, byte[] c) {
34 | return enc.encode(enc.toBigInteger(a).multiply(enc.toBigInteger(b)).add(enc.toBigInteger(c)).mod(l));
35 | }
36 |
37 | }
38 |
--------------------------------------------------------------------------------
/ext/ed25519_jruby/net/i2p/crypto/eddsa/math/bigint/package.html:
--------------------------------------------------------------------------------
1 |
2 |
3 | Low-level, non-optimized implementation using BigIntegers for any curve.
4 | See the ed25519 implementation for Curve 25519.
5 |
6 |
7 |
--------------------------------------------------------------------------------
/ext/ed25519_jruby/net/i2p/crypto/eddsa/math/ed25519/Ed25519LittleEndianEncoding.java:
--------------------------------------------------------------------------------
1 | /**
2 | * EdDSA-Java by str4d
3 | *
4 | * To the extent possible under law, the person who associated CC0 with
5 | * EdDSA-Java has waived all copyright and related or neighboring rights
6 | * to EdDSA-Java.
7 | *
8 | * You should have received a copy of the CC0 legalcode along with this
9 | * work. If not, see .
10 | *
11 | */
12 | package net.i2p.crypto.eddsa.math.ed25519;
13 |
14 | import net.i2p.crypto.eddsa.math.*;
15 |
16 | /**
17 | * Helper class for encoding/decoding from/to the 32 byte representation.
18 | *
19 | * Reviewed/commented by Bloody Rookie (nemproject@gmx.de)
20 | */
21 | public class Ed25519LittleEndianEncoding extends Encoding {
22 | /**
23 | * Encodes a given field element in its 32 byte representation. This is done in two steps:
24 | *
25 | * - Reduce the value of the field element modulo $p$.
26 | *
- Convert the field element to the 32 byte representation.
27 | *
28 | * The idea for the modulo $p$ reduction algorithm is as follows:
29 | *
30 | * Assumption:
31 | *
32 | * - $p = 2^{255} - 19$
33 | *
- $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$.
34 | *
- $h \cong r \mod p$, i.e. $h = r + q * p$ for some suitable $0 \le r \lt p$ and an integer $q$.
35 | *
36 | * Then $q = [2^{-255} * (h + 19 * 2^{-25} * h_9 + 1/2)]$ where $[x] = floor(x)$.
37 | *
38 | * Proof:
39 | *
40 | * We begin with some very raw estimation for the bounds of some expressions:
41 | *
42 | * $$
43 | * \begin{equation}
44 | * |h| \lt 2^{230} * 2^{30} = 2^{260} \Rightarrow |r + q * p| \lt 2^{260} \Rightarrow |q| \lt 2^{10}. \\
45 | * \Rightarrow -1/4 \le a := 19^2 * 2^{-255} * q \lt 1/4. \\
46 | * |h - 2^{230} * h_9| = |h_0 + \dots + 2^{204} * h_8| \lt 2^{204} * 2^{30} = 2^{234}. \\
47 | * \Rightarrow -1/4 \le b := 19 * 2^{-255} * (h - 2^{230} * h_9) \lt 1/4
48 | * \end{equation}
49 | * $$
50 | *
51 | * Therefore $0 \lt 1/2 - a - b \lt 1$.
52 | *
53 | * Set $x := r + 19 * 2^{-255} * r + 1/2 - a - b$. Then:
54 | *
55 | * $$
56 | * 0 \le x \lt 255 - 20 + 19 + 1 = 2^{255} \\
57 | * \Rightarrow 0 \le 2^{-255} * x \lt 1.
58 | * $$
59 | *
60 | * Since $q$ is an integer we have
61 | *
62 | * $$
63 | * [q + 2^{-255} * x] = q \quad (1)
64 | * $$
65 | *
66 | * Have a closer look at $x$:
67 | *
68 | * $$
69 | * \begin{align}
70 | * 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} * h_9) \\
71 | * &= 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 \\
72 | * &= h + 19 * 2^{-25} * h_9 + 1/2 - q^{255}.
73 | * \end{align}
74 | * $$
75 | *
76 | * Inserting the expression for $x$ into $(1)$ we get the desired expression for $q$.
77 | */
78 | public byte[] encode(FieldElement x) {
79 | int[] h = ((Ed25519FieldElement)x).t;
80 | int h0 = h[0];
81 | int h1 = h[1];
82 | int h2 = h[2];
83 | int h3 = h[3];
84 | int h4 = h[4];
85 | int h5 = h[5];
86 | int h6 = h[6];
87 | int h7 = h[7];
88 | int h8 = h[8];
89 | int h9 = h[9];
90 | int q;
91 | int carry0;
92 | int carry1;
93 | int carry2;
94 | int carry3;
95 | int carry4;
96 | int carry5;
97 | int carry6;
98 | int carry7;
99 | int carry8;
100 | int carry9;
101 |
102 | // Step 1:
103 | // Calculate q
104 | q = (19 * h9 + (1 << 24)) >> 25;
105 | q = (h0 + q) >> 26;
106 | q = (h1 + q) >> 25;
107 | q = (h2 + q) >> 26;
108 | q = (h3 + q) >> 25;
109 | q = (h4 + q) >> 26;
110 | q = (h5 + q) >> 25;
111 | q = (h6 + q) >> 26;
112 | q = (h7 + q) >> 25;
113 | q = (h8 + q) >> 26;
114 | q = (h9 + q) >> 25;
115 |
116 | // r = h - q * p = h - 2^255 * q + 19 * q
117 | // First add 19 * q then discard the bit 255
118 | h0 += 19 * q;
119 |
120 | carry0 = h0 >> 26; h1 += carry0; h0 -= carry0 << 26;
121 | carry1 = h1 >> 25; h2 += carry1; h1 -= carry1 << 25;
122 | carry2 = h2 >> 26; h3 += carry2; h2 -= carry2 << 26;
123 | carry3 = h3 >> 25; h4 += carry3; h3 -= carry3 << 25;
124 | carry4 = h4 >> 26; h5 += carry4; h4 -= carry4 << 26;
125 | carry5 = h5 >> 25; h6 += carry5; h5 -= carry5 << 25;
126 | carry6 = h6 >> 26; h7 += carry6; h6 -= carry6 << 26;
127 | carry7 = h7 >> 25; h8 += carry7; h7 -= carry7 << 25;
128 | carry8 = h8 >> 26; h9 += carry8; h8 -= carry8 << 26;
129 | carry9 = h9 >> 25; h9 -= carry9 << 25;
130 |
131 | // Step 2 (straight forward conversion):
132 | byte[] s = new byte[32];
133 | s[0] = (byte) h0;
134 | s[1] = (byte) (h0 >> 8);
135 | s[2] = (byte) (h0 >> 16);
136 | s[3] = (byte) ((h0 >> 24) | (h1 << 2));
137 | s[4] = (byte) (h1 >> 6);
138 | s[5] = (byte) (h1 >> 14);
139 | s[6] = (byte) ((h1 >> 22) | (h2 << 3));
140 | s[7] = (byte) (h2 >> 5);
141 | s[8] = (byte) (h2 >> 13);
142 | s[9] = (byte) ((h2 >> 21) | (h3 << 5));
143 | s[10] = (byte) (h3 >> 3);
144 | s[11] = (byte) (h3 >> 11);
145 | s[12] = (byte) ((h3 >> 19) | (h4 << 6));
146 | s[13] = (byte) (h4 >> 2);
147 | s[14] = (byte) (h4 >> 10);
148 | s[15] = (byte) (h4 >> 18);
149 | s[16] = (byte) h5;
150 | s[17] = (byte) (h5 >> 8);
151 | s[18] = (byte) (h5 >> 16);
152 | s[19] = (byte) ((h5 >> 24) | (h6 << 1));
153 | s[20] = (byte) (h6 >> 7);
154 | s[21] = (byte) (h6 >> 15);
155 | s[22] = (byte) ((h6 >> 23) | (h7 << 3));
156 | s[23] = (byte) (h7 >> 5);
157 | s[24] = (byte) (h7 >> 13);
158 | s[25] = (byte) ((h7 >> 21) | (h8 << 4));
159 | s[26] = (byte) (h8 >> 4);
160 | s[27] = (byte) (h8 >> 12);
161 | s[28] = (byte) ((h8 >> 20) | (h9 << 6));
162 | s[29] = (byte) (h9 >> 2);
163 | s[30] = (byte) (h9 >> 10);
164 | s[31] = (byte) (h9 >> 18);
165 | return s;
166 | }
167 |
168 | static int load_3(byte[] in, int offset) {
169 | int result = in[offset++] & 0xff;
170 | result |= (in[offset++] & 0xff) << 8;
171 | result |= (in[offset] & 0xff) << 16;
172 | return result;
173 | }
174 |
175 | static long load_4(byte[] in, int offset) {
176 | int result = in[offset++] & 0xff;
177 | result |= (in[offset++] & 0xff) << 8;
178 | result |= (in[offset++] & 0xff) << 16;
179 | result |= in[offset] << 24;
180 | return ((long)result) & 0xffffffffL;
181 | }
182 |
183 | /**
184 | * Decodes a given field element in its 10 byte $2^{25.5}$ representation.
185 | *
186 | * @param in The 32 byte representation.
187 | * @return The field element in its $2^{25.5}$ bit representation.
188 | */
189 | public FieldElement decode(byte[] in) {
190 | long h0 = load_4(in, 0);
191 | long h1 = load_3(in, 4) << 6;
192 | long h2 = load_3(in, 7) << 5;
193 | long h3 = load_3(in, 10) << 3;
194 | long h4 = load_3(in, 13) << 2;
195 | long h5 = load_4(in, 16);
196 | long h6 = load_3(in, 20) << 7;
197 | long h7 = load_3(in, 23) << 5;
198 | long h8 = load_3(in, 26) << 4;
199 | long h9 = (load_3(in, 29) & 0x7FFFFF) << 2;
200 | long carry0;
201 | long carry1;
202 | long carry2;
203 | long carry3;
204 | long carry4;
205 | long carry5;
206 | long carry6;
207 | long carry7;
208 | long carry8;
209 | long carry9;
210 |
211 | // Remember: 2^255 congruent 19 modulo p
212 | carry9 = (h9 + (long) (1<<24)) >> 25; h0 += carry9 * 19; h9 -= carry9 << 25;
213 | carry1 = (h1 + (long) (1<<24)) >> 25; h2 += carry1; h1 -= carry1 << 25;
214 | carry3 = (h3 + (long) (1<<24)) >> 25; h4 += carry3; h3 -= carry3 << 25;
215 | carry5 = (h5 + (long) (1<<24)) >> 25; h6 += carry5; h5 -= carry5 << 25;
216 | carry7 = (h7 + (long) (1<<24)) >> 25; h8 += carry7; h7 -= carry7 << 25;
217 |
218 | carry0 = (h0 + (long) (1<<25)) >> 26; h1 += carry0; h0 -= carry0 << 26;
219 | carry2 = (h2 + (long) (1<<25)) >> 26; h3 += carry2; h2 -= carry2 << 26;
220 | carry4 = (h4 + (long) (1<<25)) >> 26; h5 += carry4; h4 -= carry4 << 26;
221 | carry6 = (h6 + (long) (1<<25)) >> 26; h7 += carry6; h6 -= carry6 << 26;
222 | carry8 = (h8 + (long) (1<<25)) >> 26; h9 += carry8; h8 -= carry8 << 26;
223 |
224 | int[] h = new int[10];
225 | h[0] = (int) h0;
226 | h[1] = (int) h1;
227 | h[2] = (int) h2;
228 | h[3] = (int) h3;
229 | h[4] = (int) h4;
230 | h[5] = (int) h5;
231 | h[6] = (int) h6;
232 | h[7] = (int) h7;
233 | h[8] = (int) h8;
234 | h[9] = (int) h9;
235 | return new Ed25519FieldElement(f, h);
236 | }
237 |
238 | /**
239 | * Is the FieldElement negative in this encoding?
240 | *
241 | * Return true if $x$ is in $\{1,3,5,\dots,q-2\}$
242 | * Return false if $x$ is in $\{0,2,4,\dots,q-1\}$
243 | *
244 | * Preconditions:
245 | *
246 | * - $|x|$ bounded by $1.1*2^{26},1.1*2^{25},1.1*2^{26},1.1*2^{25}$, etc.
247 | *
248 | *
249 | * @return true if $x$ is in $\{1,3,5,\dots,q-2\}$, false otherwise.
250 | */
251 | public boolean isNegative(FieldElement x) {
252 | byte[] s = encode(x);
253 | return (s[0] & 1) != 0;
254 | }
255 |
256 | }
257 |
--------------------------------------------------------------------------------
/ext/ed25519_jruby/net/i2p/crypto/eddsa/spec/EdDSAGenParameterSpec.java:
--------------------------------------------------------------------------------
1 | /**
2 | * EdDSA-Java by str4d
3 | *
4 | * To the extent possible under law, the person who associated CC0 with
5 | * EdDSA-Java has waived all copyright and related or neighboring rights
6 | * to EdDSA-Java.
7 | *
8 | * You should have received a copy of the CC0 legalcode along with this
9 | * work. If not, see .
10 | *
11 | */
12 | package net.i2p.crypto.eddsa.spec;
13 |
14 | import java.security.spec.AlgorithmParameterSpec;
15 |
16 | /**
17 | * Implementation of AlgorithmParameterSpec that holds the name of a named
18 | * EdDSA curve specification.
19 | * @author str4d
20 | *
21 | */
22 | public class EdDSAGenParameterSpec implements AlgorithmParameterSpec {
23 | private final String name;
24 |
25 | public EdDSAGenParameterSpec(String stdName) {
26 | name = stdName;
27 | }
28 |
29 | public String getName() {
30 | return name;
31 | }
32 | }
33 |
--------------------------------------------------------------------------------
/ext/ed25519_jruby/net/i2p/crypto/eddsa/spec/EdDSANamedCurveSpec.java:
--------------------------------------------------------------------------------
1 | /**
2 | * EdDSA-Java by str4d
3 | *
4 | * To the extent possible under law, the person who associated CC0 with
5 | * EdDSA-Java has waived all copyright and related or neighboring rights
6 | * to EdDSA-Java.
7 | *
8 | * You should have received a copy of the CC0 legalcode along with this
9 | * work. If not, see .
10 | *
11 | */
12 | package net.i2p.crypto.eddsa.spec;
13 |
14 | import net.i2p.crypto.eddsa.math.Curve;
15 | import net.i2p.crypto.eddsa.math.GroupElement;
16 | import net.i2p.crypto.eddsa.math.ScalarOps;
17 |
18 | /**
19 | * EdDSA Curve specification that can also be referred to by name.
20 | * @author str4d
21 | *
22 | */
23 | public class EdDSANamedCurveSpec extends EdDSAParameterSpec {
24 | private final String name;
25 |
26 | public EdDSANamedCurveSpec(String name, Curve curve,
27 | String hashAlgo, ScalarOps sc, GroupElement B) {
28 | super(curve, hashAlgo, sc, B);
29 | this.name = name;
30 | }
31 |
32 | public String getName() {
33 | return name;
34 | }
35 | }
36 |
--------------------------------------------------------------------------------
/ext/ed25519_jruby/net/i2p/crypto/eddsa/spec/EdDSANamedCurveTable.java:
--------------------------------------------------------------------------------
1 | /**
2 | * EdDSA-Java by str4d
3 | *
4 | * To the extent possible under law, the person who associated CC0 with
5 | * EdDSA-Java has waived all copyright and related or neighboring rights
6 | * to EdDSA-Java.
7 | *
8 | * You should have received a copy of the CC0 legalcode along with this
9 | * work. If not, see .
10 | *
11 | */
12 | package net.i2p.crypto.eddsa.spec;
13 |
14 | import java.util.Hashtable;
15 | import java.util.Locale;
16 |
17 | import net.i2p.crypto.eddsa.Utils;
18 | import net.i2p.crypto.eddsa.math.Curve;
19 | import net.i2p.crypto.eddsa.math.Field;
20 | import net.i2p.crypto.eddsa.math.ed25519.Ed25519LittleEndianEncoding;
21 | import net.i2p.crypto.eddsa.math.ed25519.Ed25519ScalarOps;
22 |
23 | /**
24 | * The named EdDSA curves.
25 | * @author str4d
26 | *
27 | */
28 | public class EdDSANamedCurveTable {
29 | public static final String ED_25519 = "Ed25519";
30 |
31 | private static final Field ed25519field = new Field(
32 | 256, // b
33 | Utils.hexToBytes("edffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f"), // q
34 | new Ed25519LittleEndianEncoding());
35 |
36 | private static final Curve ed25519curve = new Curve(ed25519field,
37 | Utils.hexToBytes("a3785913ca4deb75abd841414d0a700098e879777940c78c73fe6f2bee6c0352"), // d
38 | ed25519field.fromByteArray(Utils.hexToBytes("b0a00e4a271beec478e42fad0618432fa7d7fb3d99004d2b0bdfc14f8024832b"))); // I
39 |
40 | private static final EdDSANamedCurveSpec ed25519 = new EdDSANamedCurveSpec(
41 | ED_25519,
42 | ed25519curve,
43 | "SHA-512", // H
44 | new Ed25519ScalarOps(), // l
45 | ed25519curve.createPoint( // B
46 | Utils.hexToBytes("5866666666666666666666666666666666666666666666666666666666666666"),
47 | true)); // Precompute tables for B
48 |
49 | private static final Hashtable curves = new Hashtable();
50 |
51 | public static void defineCurve(EdDSANamedCurveSpec curve) {
52 | curves.put(curve.getName().toLowerCase(Locale.ENGLISH), curve);
53 | }
54 |
55 | static void defineCurveAlias(String name, String alias) {
56 | EdDSANamedCurveSpec curve = curves.get(name.toLowerCase(Locale.ENGLISH));
57 | if (curve == null) {
58 | throw new IllegalStateException();
59 | }
60 | curves.put(alias.toLowerCase(Locale.ENGLISH), curve);
61 | }
62 |
63 | static {
64 | // RFC 8032
65 | defineCurve(ed25519);
66 | }
67 |
68 | public static EdDSANamedCurveSpec getByName(String name) {
69 | return curves.get(name.toLowerCase(Locale.ENGLISH));
70 | }
71 | }
72 |
--------------------------------------------------------------------------------
/ext/ed25519_jruby/net/i2p/crypto/eddsa/spec/EdDSAParameterSpec.java:
--------------------------------------------------------------------------------
1 | /**
2 | * EdDSA-Java by str4d
3 | *
4 | * To the extent possible under law, the person who associated CC0 with
5 | * EdDSA-Java has waived all copyright and related or neighboring rights
6 | * to EdDSA-Java.
7 | *
8 | * You should have received a copy of the CC0 legalcode along with this
9 | * work. If not, see .
10 | *
11 | */
12 | package net.i2p.crypto.eddsa.spec;
13 |
14 | import java.security.MessageDigest;
15 | import java.security.NoSuchAlgorithmException;
16 | import java.security.spec.AlgorithmParameterSpec;
17 |
18 | import net.i2p.crypto.eddsa.math.Curve;
19 | import net.i2p.crypto.eddsa.math.GroupElement;
20 | import net.i2p.crypto.eddsa.math.ScalarOps;
21 |
22 | import java.io.Serializable;
23 |
24 | /**
25 | * Parameter specification for an EdDSA algorithm.
26 | * @author str4d
27 | *
28 | */
29 | public class EdDSAParameterSpec implements AlgorithmParameterSpec, Serializable {
30 | private static final long serialVersionUID = 8274987108472012L;
31 | private final Curve curve;
32 | private final String hashAlgo;
33 | private final ScalarOps sc;
34 | private final GroupElement B;
35 |
36 | /**
37 | * @param curve the curve
38 | * @param hashAlgo the JCA string for the hash algorithm
39 | * @param sc the parameter L represented as ScalarOps
40 | * @param B the parameter B
41 | * @throws IllegalArgumentException if hash algorithm is unsupported or length is wrong
42 | */
43 | public EdDSAParameterSpec(Curve curve, String hashAlgo,
44 | ScalarOps sc, GroupElement B) {
45 | try {
46 | MessageDigest hash = MessageDigest.getInstance(hashAlgo);
47 | // EdDSA hash function must produce 2b-bit output
48 | if (curve.getField().getb()/4 != hash.getDigestLength())
49 | throw new IllegalArgumentException("Hash output is not 2b-bit");
50 | } catch (NoSuchAlgorithmException e) {
51 | throw new IllegalArgumentException("Unsupported hash algorithm");
52 | }
53 |
54 | this.curve = curve;
55 | this.hashAlgo = hashAlgo;
56 | this.sc = sc;
57 | this.B = B;
58 | }
59 |
60 | public Curve getCurve() {
61 | return curve;
62 | }
63 |
64 | public String getHashAlgorithm() {
65 | return hashAlgo;
66 | }
67 |
68 | public ScalarOps getScalarOps() {
69 | return sc;
70 | }
71 |
72 | /**
73 | * @return the base (generator)
74 | */
75 | public GroupElement getB() {
76 | return B;
77 | }
78 |
79 | @Override
80 | public int hashCode() {
81 | return hashAlgo.hashCode() ^
82 | curve.hashCode() ^
83 | B.hashCode();
84 | }
85 |
86 | @Override
87 | public boolean equals(Object o) {
88 | if (o == this)
89 | return true;
90 | if (!(o instanceof EdDSAParameterSpec))
91 | return false;
92 | EdDSAParameterSpec s = (EdDSAParameterSpec) o;
93 | return hashAlgo.equals(s.getHashAlgorithm()) &&
94 | curve.equals(s.getCurve()) &&
95 | B.equals(s.getB());
96 | }
97 | }
98 |
--------------------------------------------------------------------------------
/ext/ed25519_jruby/net/i2p/crypto/eddsa/spec/EdDSAPrivateKeySpec.java:
--------------------------------------------------------------------------------
1 | /**
2 | * EdDSA-Java by str4d
3 | *
4 | * To the extent possible under law, the person who associated CC0 with
5 | * EdDSA-Java has waived all copyright and related or neighboring rights
6 | * to EdDSA-Java.
7 | *
8 | * You should have received a copy of the CC0 legalcode along with this
9 | * work. If not, see .
10 | *
11 | */
12 | package net.i2p.crypto.eddsa.spec;
13 |
14 | import java.security.MessageDigest;
15 | import java.security.NoSuchAlgorithmException;
16 | import java.security.spec.KeySpec;
17 | import java.util.Arrays;
18 |
19 | import net.i2p.crypto.eddsa.math.GroupElement;
20 |
21 | /**
22 | * @author str4d
23 | *
24 | */
25 | public class EdDSAPrivateKeySpec implements KeySpec {
26 | private final byte[] seed;
27 | private final byte[] h;
28 | private final byte[] a;
29 | private final GroupElement A;
30 | private final EdDSAParameterSpec spec;
31 |
32 | /**
33 | * @param seed the private key
34 | * @param spec the parameter specification for this key
35 | * @throws IllegalArgumentException if seed length is wrong or hash algorithm is unsupported
36 | */
37 | public EdDSAPrivateKeySpec(byte[] seed, EdDSAParameterSpec spec) {
38 | if (seed.length != spec.getCurve().getField().getb()/8)
39 | throw new IllegalArgumentException("seed length is wrong");
40 |
41 | this.spec = spec;
42 | this.seed = seed;
43 |
44 | try {
45 | MessageDigest hash = MessageDigest.getInstance(spec.getHashAlgorithm());
46 | int b = spec.getCurve().getField().getb();
47 |
48 | // H(k)
49 | h = hash.digest(seed);
50 |
51 | /*a = BigInteger.valueOf(2).pow(b-2);
52 | for (int i=3;i<(b-2);i++) {
53 | a = a.add(BigInteger.valueOf(2).pow(i).multiply(BigInteger.valueOf(Utils.bit(h,i))));
54 | }*/
55 | // Saves ~0.4ms per key when running signing tests.
56 | // TODO: are these bitflips the same for any hash function?
57 | h[0] &= 248;
58 | h[(b/8)-1] &= 63;
59 | h[(b/8)-1] |= 64;
60 | a = Arrays.copyOfRange(h, 0, b/8);
61 |
62 | A = spec.getB().scalarMultiply(a);
63 | } catch (NoSuchAlgorithmException e) {
64 | throw new IllegalArgumentException("Unsupported hash algorithm");
65 | }
66 | }
67 |
68 | /**
69 | * Initialize directly from the hash.
70 | * getSeed() will return null if this constructor is used.
71 | *
72 | * @param spec the parameter specification for this key
73 | * @param h the private key
74 | * @throws IllegalArgumentException if hash length is wrong
75 | * @since 0.1.1
76 | */
77 | public EdDSAPrivateKeySpec(EdDSAParameterSpec spec, byte[] h) {
78 | if (h.length != spec.getCurve().getField().getb()/4)
79 | throw new IllegalArgumentException("hash length is wrong");
80 |
81 | this.seed = null;
82 | this.h = h;
83 | this.spec = spec;
84 | int b = spec.getCurve().getField().getb();
85 |
86 | h[0] &= 248;
87 | h[(b/8)-1] &= 63;
88 | h[(b/8)-1] |= 64;
89 | a = Arrays.copyOfRange(h, 0, b/8);
90 |
91 | A = spec.getB().scalarMultiply(a);
92 | }
93 |
94 | public EdDSAPrivateKeySpec(byte[] seed, byte[] h, byte[] a, GroupElement A, EdDSAParameterSpec spec) {
95 | this.seed = seed;
96 | this.h = h;
97 | this.a = a;
98 | this.A = A;
99 | this.spec = spec;
100 | }
101 |
102 | /**
103 | * @return will be null if constructed directly from the private key
104 | */
105 | public byte[] getSeed() {
106 | return seed;
107 | }
108 |
109 | /**
110 | * @return the hash
111 | */
112 | public byte[] getH() {
113 | return h;
114 | }
115 |
116 | /**
117 | * @return the private key
118 | */
119 | public byte[] geta() {
120 | return a;
121 | }
122 |
123 | /**
124 | * @return the public key
125 | */
126 | public GroupElement getA() {
127 | return A;
128 | }
129 |
130 | public EdDSAParameterSpec getParams() {
131 | return spec;
132 | }
133 | }
134 |
--------------------------------------------------------------------------------
/ext/ed25519_jruby/net/i2p/crypto/eddsa/spec/EdDSAPublicKeySpec.java:
--------------------------------------------------------------------------------
1 | /**
2 | * EdDSA-Java by str4d
3 | *
4 | * To the extent possible under law, the person who associated CC0 with
5 | * EdDSA-Java has waived all copyright and related or neighboring rights
6 | * to EdDSA-Java.
7 | *
8 | * You should have received a copy of the CC0 legalcode along with this
9 | * work. If not, see .
10 | *
11 | */
12 | package net.i2p.crypto.eddsa.spec;
13 |
14 | import java.security.spec.KeySpec;
15 |
16 | import net.i2p.crypto.eddsa.math.GroupElement;
17 |
18 | /**
19 | * @author str4d
20 | *
21 | */
22 | public class EdDSAPublicKeySpec implements KeySpec {
23 | private final GroupElement A;
24 | private final GroupElement Aneg;
25 | private final EdDSAParameterSpec spec;
26 |
27 | /**
28 | * @param pk the public key
29 | * @param spec the parameter specification for this key
30 | * @throws IllegalArgumentException if key length is wrong
31 | */
32 | public EdDSAPublicKeySpec(byte[] pk, EdDSAParameterSpec spec) {
33 | if (pk.length != spec.getCurve().getField().getb()/8)
34 | throw new IllegalArgumentException("public-key length is wrong");
35 |
36 | this.A = new GroupElement(spec.getCurve(), pk);
37 | // Precompute -A for use in verification.
38 | this.Aneg = A.negate();
39 | Aneg.precompute(false);
40 | this.spec = spec;
41 | }
42 |
43 | public EdDSAPublicKeySpec(GroupElement A, EdDSAParameterSpec spec) {
44 | this.A = A;
45 | this.Aneg = A.negate();
46 | Aneg.precompute(false);
47 | this.spec = spec;
48 | }
49 |
50 | public GroupElement getA() {
51 | return A;
52 | }
53 |
54 | public GroupElement getNegativeA() {
55 | return Aneg;
56 | }
57 |
58 | public EdDSAParameterSpec getParams() {
59 | return spec;
60 | }
61 | }
62 |
--------------------------------------------------------------------------------
/ext/ed25519_jruby/org/cryptorb/Ed25519Provider.java:
--------------------------------------------------------------------------------
1 | package org.cryptorb;
2 |
3 | import java.security.MessageDigest;
4 | import java.security.Signature;
5 | import java.util.Arrays;
6 | import net.i2p.crypto.eddsa.EdDSAEngine;
7 | import net.i2p.crypto.eddsa.EdDSAPrivateKey;
8 | import net.i2p.crypto.eddsa.EdDSAPublicKey;
9 | import net.i2p.crypto.eddsa.spec.EdDSANamedCurveTable;
10 | import net.i2p.crypto.eddsa.spec.EdDSAParameterSpec;
11 | import net.i2p.crypto.eddsa.spec.EdDSAPrivateKeySpec;
12 | import net.i2p.crypto.eddsa.spec.EdDSAPublicKeySpec;
13 | import org.jruby.Ruby;
14 | import org.jruby.RubyModule;
15 | import org.jruby.RubyString;
16 | import org.jruby.anno.JRubyMethod;
17 | import org.jruby.anno.JRubyModule;
18 | import org.jruby.runtime.ThreadContext;
19 | import org.jruby.runtime.builtin.IRubyObject;
20 |
21 | @JRubyModule(name="Ed25519::Provider::JRuby")
22 | public class Ed25519Provider {
23 | public static RubyModule createEd25519Module(Ruby runtime) {
24 | RubyModule mEd25519 = runtime.defineModule("Ed25519");
25 | RubyModule mEd25519Provider = mEd25519.defineModuleUnder("Provider");
26 | RubyModule mEd25519ProviderJRuby = mEd25519Provider.defineOrGetModuleUnder("JRuby");
27 | mEd25519ProviderJRuby.defineAnnotatedMethods(Ed25519Provider.class);
28 |
29 | return mEd25519ProviderJRuby;
30 | }
31 |
32 | @JRubyMethod(name = "create_keypair", module = true)
33 | public static IRubyObject create_keypair(ThreadContext context, IRubyObject self, IRubyObject seed) {
34 | byte[] seedBytes = seed.convertToString().getByteList().bytes();
35 |
36 | if (seedBytes.length != 32) {
37 | throw context.runtime.newArgumentError("expected 32-byte seed value, got " + seedBytes.length);
38 | }
39 |
40 | EdDSAParameterSpec edParams = EdDSANamedCurveTable.getByName(EdDSANamedCurveTable.ED_25519);
41 | EdDSAPrivateKeySpec signingKey = new EdDSAPrivateKeySpec(seedBytes, edParams);
42 | EdDSAPublicKeySpec verifyKey = new EdDSAPublicKeySpec(signingKey.getA(), edParams);
43 |
44 | byte[] keypair = new byte[64];
45 |
46 | System.arraycopy(seedBytes, 0, keypair, 0, 32);
47 | System.arraycopy(verifyKey.getA().toByteArray(), 0, keypair, 32, 32);
48 |
49 | return RubyString.newString(context.getRuntime(), keypair);
50 | }
51 |
52 | @JRubyMethod(name = "sign", module = true)
53 | public static IRubyObject sign(ThreadContext context, IRubyObject self, IRubyObject keypair, IRubyObject msg) throws Exception {
54 | byte[] keypairBytes = keypair.convertToString().getByteList().bytes();
55 |
56 | if (keypairBytes.length != 64) {
57 | throw context.runtime.newArgumentError("expected 64-byte keypair value, got " + keypairBytes.length);
58 | }
59 |
60 | EdDSAParameterSpec edParams = EdDSANamedCurveTable.getByName(EdDSANamedCurveTable.ED_25519);
61 | Signature signer = new EdDSAEngine(MessageDigest.getInstance(edParams.getHashAlgorithm()));
62 |
63 | byte[] seedBytes = Arrays.copyOfRange(keypairBytes, 0, 32);
64 | EdDSAPrivateKeySpec signingKey = new EdDSAPrivateKeySpec(seedBytes, edParams);
65 |
66 | signer.initSign(new EdDSAPrivateKey(signingKey));
67 | signer.update(msg.convertToString().getByteList().bytes());
68 |
69 | return RubyString.newString(context.getRuntime(), signer.sign());
70 | }
71 |
72 | @JRubyMethod(name = "verify", module = true)
73 | public static IRubyObject verify(ThreadContext context, IRubyObject self, IRubyObject verify_key, IRubyObject signature, IRubyObject msg) throws Exception {
74 | byte[] verifyKeyBytes = verify_key.convertToString().getByteList().bytes();
75 | byte[] signatureBytes = signature.convertToString().getByteList().bytes();
76 |
77 | if (verifyKeyBytes.length != 32) {
78 | throw context.runtime.newArgumentError("expected 32-byte verify key, got " + verifyKeyBytes.length);
79 | }
80 |
81 | if (signatureBytes.length != 64) {
82 | throw context.runtime.newArgumentError("expected 64-byte signature, got " + signatureBytes.length);
83 | }
84 |
85 | EdDSAParameterSpec edParams = EdDSANamedCurveTable.getByName(EdDSANamedCurveTable.ED_25519);
86 | Signature signer = new EdDSAEngine(MessageDigest.getInstance(edParams.getHashAlgorithm()));
87 | EdDSAPublicKeySpec verifyKey = new EdDSAPublicKeySpec(verifyKeyBytes, edParams);
88 |
89 | signer.initVerify(new EdDSAPublicKey(verifyKey));
90 | signer.update(msg.convertToString().getByteList().bytes());
91 |
92 | boolean isValid = signer.verify(signatureBytes);
93 | return context.runtime.newBoolean(isValid);
94 | }
95 | }
96 |
--------------------------------------------------------------------------------
/ext/ed25519_ref10/api.h:
--------------------------------------------------------------------------------
1 | #define CRYPTO_SECRETKEYBYTES 64
2 | #define CRYPTO_PUBLICKEYBYTES 32
3 | #define CRYPTO_BYTES 64
4 | #define CRYPTO_DETERMINISTIC 1
5 |
--------------------------------------------------------------------------------
/ext/ed25519_ref10/base2.h:
--------------------------------------------------------------------------------
1 | {
2 | { 25967493,-14356035,29566456,3660896,-12694345,4014787,27544626,-11754271,-6079156,2047605 },
3 | { -12545711,934262,-2722910,3049990,-727428,9406986,12720692,5043384,19500929,-15469378 },
4 | { -8738181,4489570,9688441,-14785194,10184609,-12363380,29287919,11864899,-24514362,-4438546 },
5 | },
6 | {
7 | { 15636291,-9688557,24204773,-7912398,616977,-16685262,27787600,-14772189,28944400,-1550024 },
8 | { 16568933,4717097,-11556148,-1102322,15682896,-11807043,16354577,-11775962,7689662,11199574 },
9 | { 30464156,-5976125,-11779434,-15670865,23220365,15915852,7512774,10017326,-17749093,-9920357 },
10 | },
11 | {
12 | { 10861363,11473154,27284546,1981175,-30064349,12577861,32867885,14515107,-15438304,10819380 },
13 | { 4708026,6336745,20377586,9066809,-11272109,6594696,-25653668,12483688,-12668491,5581306 },
14 | { 19563160,16186464,-29386857,4097519,10237984,-4348115,28542350,13850243,-23678021,-15815942 },
15 | },
16 | {
17 | { 5153746,9909285,1723747,-2777874,30523605,5516873,19480852,5230134,-23952439,-15175766 },
18 | { -30269007,-3463509,7665486,10083793,28475525,1649722,20654025,16520125,30598449,7715701 },
19 | { 28881845,14381568,9657904,3680757,-20181635,7843316,-31400660,1370708,29794553,-1409300 },
20 | },
21 | {
22 | { -22518993,-6692182,14201702,-8745502,-23510406,8844726,18474211,-1361450,-13062696,13821877 },
23 | { -6455177,-7839871,3374702,-4740862,-27098617,-10571707,31655028,-7212327,18853322,-14220951 },
24 | { 4566830,-12963868,-28974889,-12240689,-7602672,-2830569,-8514358,-10431137,2207753,-3209784 },
25 | },
26 | {
27 | { -25154831,-4185821,29681144,7868801,-6854661,-9423865,-12437364,-663000,-31111463,-16132436 },
28 | { 25576264,-2703214,7349804,-11814844,16472782,9300885,3844789,15725684,171356,6466918 },
29 | { 23103977,13316479,9739013,-16149481,817875,-15038942,8965339,-14088058,-30714912,16193877 },
30 | },
31 | {
32 | { -33521811,3180713,-2394130,14003687,-16903474,-16270840,17238398,4729455,-18074513,9256800 },
33 | { -25182317,-4174131,32336398,5036987,-21236817,11360617,22616405,9761698,-19827198,630305 },
34 | { -13720693,2639453,-24237460,-7406481,9494427,-5774029,-6554551,-15960994,-2449256,-14291300 },
35 | },
36 | {
37 | { -3151181,-5046075,9282714,6866145,-31907062,-863023,-18940575,15033784,25105118,-7894876 },
38 | { -24326370,15950226,-31801215,-14592823,-11662737,-5090925,1573892,-2625887,2198790,-15804619 },
39 | { -3099351,10324967,-2241613,7453183,-5446979,-2735503,-13812022,-16236442,-32461234,-12290683 },
40 | },
41 |
--------------------------------------------------------------------------------
/ext/ed25519_ref10/d.h:
--------------------------------------------------------------------------------
1 | -10913610,13857413,-15372611,6949391,114729,-8787816,-6275908,-3247719,-18696448,-12055116
2 |
--------------------------------------------------------------------------------
/ext/ed25519_ref10/d2.h:
--------------------------------------------------------------------------------
1 | -21827239,-5839606,-30745221,13898782,229458,15978800,-12551817,-6495438,29715968,9444199
2 |
--------------------------------------------------------------------------------
/ext/ed25519_ref10/ed25519_ref10.c:
--------------------------------------------------------------------------------
1 | #include "ruby.h"
2 | #include "ed25519_ref10.h"
3 |
4 | static VALUE mEd25519 = Qnil;
5 | static VALUE mEd25519_Provider = Qnil;
6 | static VALUE mEd25519_Provider_Ref10 = Qnil;
7 |
8 | static VALUE mEd25519_Provider_Ref10_create_keypair(VALUE self, VALUE seed);
9 | static VALUE mEd25519_Provider_Ref10_sign(VALUE self, VALUE signing_key, VALUE msg);
10 | static VALUE mEd25519_Provider_Ref10_verify(VALUE self, VALUE verify_key, VALUE signature, VALUE msg);
11 |
12 | void Init_ed25519_ref10()
13 | {
14 | mEd25519 = rb_define_module("Ed25519");
15 | mEd25519_Provider = rb_define_module_under(mEd25519, "Provider");
16 | mEd25519_Provider_Ref10 = rb_define_module_under(mEd25519_Provider, "Ref10");
17 |
18 | rb_define_singleton_method(mEd25519_Provider_Ref10, "create_keypair", mEd25519_Provider_Ref10_create_keypair, 1);
19 | rb_define_singleton_method(mEd25519_Provider_Ref10, "sign", mEd25519_Provider_Ref10_sign, 2);
20 | rb_define_singleton_method(mEd25519_Provider_Ref10, "verify", mEd25519_Provider_Ref10_verify, 3);
21 | }
22 |
23 | static VALUE mEd25519_Provider_Ref10_create_keypair(VALUE self, VALUE seed)
24 | {
25 | uint8_t verify_key[PUBLICKEYBYTES];
26 | uint8_t keypair[SECRETKEYBYTES];
27 |
28 | StringValue(seed);
29 |
30 | if(RSTRING_LEN(seed) != SECRETKEYBYTES / 2) {
31 | rb_raise(rb_eArgError, "seed must be exactly %d bytes", SECRETKEYBYTES / 2);
32 | }
33 |
34 | crypto_sign_ed25519_ref10_seed_keypair(verify_key, keypair, (uint8_t *)RSTRING_PTR(seed));
35 |
36 | return rb_str_new((const char *)keypair, SECRETKEYBYTES);
37 | }
38 |
39 | static VALUE mEd25519_Provider_Ref10_sign(VALUE self, VALUE signing_key, VALUE msg)
40 | {
41 | uint8_t *sig_and_msg;
42 | uint64_t sig_and_msg_len;
43 | VALUE result;
44 |
45 | StringValue(signing_key);
46 | StringValue(msg);
47 |
48 | if(RSTRING_LEN(signing_key) != SECRETKEYBYTES) {
49 | rb_raise(rb_eArgError, "private signing keys must be %d bytes", SECRETKEYBYTES);
50 | }
51 |
52 | sig_and_msg = (uint8_t *)xmalloc(SIGNATUREBYTES + RSTRING_LEN(msg));
53 | crypto_sign_ed25519_ref10(
54 | sig_and_msg, &sig_and_msg_len,
55 | (uint8_t *)RSTRING_PTR(msg), RSTRING_LEN(msg),
56 | (uint8_t *)RSTRING_PTR(signing_key)
57 | );
58 |
59 | result = rb_str_new((const char *)sig_and_msg, SIGNATUREBYTES);
60 | xfree(sig_and_msg);
61 |
62 | return result;
63 | }
64 |
65 | static VALUE mEd25519_Provider_Ref10_verify(VALUE self, VALUE verify_key, VALUE signature, VALUE msg)
66 | {
67 | uint8_t *sig_and_msg, *buffer;
68 | uint64_t sig_and_msg_len, buffer_len;
69 | int result;
70 |
71 | StringValue(verify_key);
72 | StringValue(signature);
73 | StringValue(msg);
74 |
75 | if(RSTRING_LEN(verify_key) != PUBLICKEYBYTES) {
76 | rb_raise(rb_eArgError, "public verify keys must be %d bytes", PUBLICKEYBYTES);
77 | }
78 |
79 | if(RSTRING_LEN(signature) != SIGNATUREBYTES) {
80 | rb_raise(rb_eArgError, "signatures must be %d bytes", SIGNATUREBYTES);
81 | }
82 |
83 | sig_and_msg_len = SIGNATUREBYTES + RSTRING_LEN(msg);
84 | sig_and_msg = (unsigned char *)xmalloc(sig_and_msg_len);
85 | buffer = (unsigned char *)xmalloc(sig_and_msg_len);
86 | memcpy(sig_and_msg, RSTRING_PTR(signature), SIGNATUREBYTES);
87 | memcpy(sig_and_msg + SIGNATUREBYTES, RSTRING_PTR(msg), RSTRING_LEN(msg));
88 |
89 | result = crypto_sign_open_ed25519_ref10(
90 | buffer, &buffer_len,
91 | sig_and_msg, sig_and_msg_len,
92 | (uint8_t *)RSTRING_PTR(verify_key)
93 | );
94 |
95 | xfree(sig_and_msg);
96 | xfree(buffer);
97 |
98 | return result == 0 ? Qtrue : Qfalse;
99 | }
100 |
--------------------------------------------------------------------------------
/ext/ed25519_ref10/ed25519_ref10.h:
--------------------------------------------------------------------------------
1 | #ifndef ED25519_REF10_H
2 | #define ED25519_REF10_H
3 |
4 | #include
5 |
6 | #define SECRETKEYBYTES 64
7 | #define PUBLICKEYBYTES 32
8 | #define SIGNATUREBYTES 64
9 |
10 | #define ED25519_KEYSIZE_BYTES 32
11 | typedef uint8_t ED25519_KEY[ED25519_KEYSIZE_BYTES];
12 |
13 | /* Generate an Ed25519 keypair from a seed value */
14 | int crypto_sign_ed25519_ref10_seed_keypair(uint8_t *pk, uint8_t *sk, const uint8_t *seed);
15 |
16 | /* Compute an Ed25519 signature over the given message */
17 | int crypto_sign_ed25519_ref10(
18 | uint8_t *sm, uint64_t *smlen,
19 | const uint8_t *m, uint64_t mlen,
20 | const uint8_t *sk
21 | );
22 |
23 | /* Verify the given signature is authentic */
24 | int crypto_sign_open_ed25519_ref10(
25 | uint8_t *m, uint64_t *mlen,
26 | const uint8_t *sm, uint64_t smlen,
27 | const uint8_t *pk
28 | );
29 |
30 | /* Constant-time comparison function */
31 | int crypto_verify_32(const uint8_t *x,const uint8_t *y);
32 |
33 | #endif /* ED25519_REF10_H */
34 |
--------------------------------------------------------------------------------
/ext/ed25519_ref10/extconf.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 |
3 | require "mkmf"
4 |
5 | append_cflags(["-Wall", "-O3", "-pedantic", "-std=c99"])
6 |
7 | create_makefile "ed25519_ref10"
8 |
--------------------------------------------------------------------------------
/ext/ed25519_ref10/fe.h:
--------------------------------------------------------------------------------
1 | #ifndef FE_H
2 | #define FE_H
3 |
4 | #include "ed25519_ref10.h"
5 |
6 | typedef int32_t fe[10];
7 |
8 | /*
9 | fe means field element.
10 | Here the field is \Z/(2^255-19).
11 | An element t, entries t[0]...t[9], represents the integer
12 | t[0]+2^26 t[1]+2^51 t[2]+2^77 t[3]+2^102 t[4]+...+2^230 t[9].
13 | Bounds on each t[i] vary depending on context.
14 | */
15 |
16 | #define fe_frombytes crypto_sign_ed25519_ref10_fe_frombytes
17 | #define fe_tobytes crypto_sign_ed25519_ref10_fe_tobytes
18 | #define fe_copy crypto_sign_ed25519_ref10_fe_copy
19 | #define fe_isnonzero crypto_sign_ed25519_ref10_fe_isnonzero
20 | #define fe_isnegative crypto_sign_ed25519_ref10_fe_isnegative
21 | #define fe_0 crypto_sign_ed25519_ref10_fe_0
22 | #define fe_1 crypto_sign_ed25519_ref10_fe_1
23 | #define fe_cswap crypto_sign_ed25519_ref10_fe_cswap
24 | #define fe_cmov crypto_sign_ed25519_ref10_fe_cmov
25 | #define fe_add crypto_sign_ed25519_ref10_fe_add
26 | #define fe_sub crypto_sign_ed25519_ref10_fe_sub
27 | #define fe_neg crypto_sign_ed25519_ref10_fe_neg
28 | #define fe_mul crypto_sign_ed25519_ref10_fe_mul
29 | #define fe_sq crypto_sign_ed25519_ref10_fe_sq
30 | #define fe_sq2 crypto_sign_ed25519_ref10_fe_sq2
31 | #define fe_mul121666 crypto_sign_ed25519_ref10_fe_mul121666
32 | #define fe_invert crypto_sign_ed25519_ref10_fe_invert
33 | #define fe_pow22523 crypto_sign_ed25519_ref10_fe_pow22523
34 |
35 | extern void fe_frombytes(fe,const unsigned char *);
36 | extern void fe_tobytes(unsigned char *,const fe);
37 |
38 | extern void fe_copy(fe,const fe);
39 | extern int fe_isnonzero(const fe);
40 | extern int fe_isnegative(const fe);
41 | extern void fe_0(fe);
42 | extern void fe_1(fe);
43 | extern void fe_cswap(fe,fe,unsigned int);
44 | extern void fe_cmov(fe,const fe,unsigned int);
45 |
46 | extern void fe_add(fe,const fe,const fe);
47 | extern void fe_sub(fe,const fe,const fe);
48 | extern void fe_neg(fe,const fe);
49 | extern void fe_mul(fe,const fe,const fe);
50 | extern void fe_sq(fe,const fe);
51 | extern void fe_sq2(fe,const fe);
52 | extern void fe_mul121666(fe,const fe);
53 | extern void fe_invert(fe,const fe);
54 | extern void fe_pow22523(fe,const fe);
55 |
56 | #endif
57 |
--------------------------------------------------------------------------------
/ext/ed25519_ref10/ge.c:
--------------------------------------------------------------------------------
1 | #include "ge.h"
2 |
3 | /*
4 | r = p + q
5 | */
6 |
7 | void ge_add(ge_p1p1 *r,const ge_p3 *p,const ge_cached *q)
8 | {
9 | fe t0;
10 | #include "ge_add.h"
11 | }
12 |
13 | static void slide(signed char *r,const unsigned char *a)
14 | {
15 | int i;
16 | int b;
17 | int k;
18 |
19 | for (i = 0;i < 256;++i)
20 | r[i] = 1 & (a[i >> 3] >> (i & 7));
21 |
22 | for (i = 0;i < 256;++i)
23 | if (r[i]) {
24 | for (b = 1;b <= 6 && i + b < 256;++b) {
25 | if (r[i + b]) {
26 | if (r[i] + (r[i + b] << b) <= 15) {
27 | r[i] += r[i + b] << b; r[i + b] = 0;
28 | } else if (r[i] - (r[i + b] << b) >= -15) {
29 | r[i] -= r[i + b] << b;
30 | for (k = i + b;k < 256;++k) {
31 | if (!r[k]) {
32 | r[k] = 1;
33 | break;
34 | }
35 | r[k] = 0;
36 | }
37 | } else
38 | break;
39 | }
40 | }
41 | }
42 |
43 | }
44 |
45 | static ge_precomp Bi[8] = {
46 | #include "base2.h"
47 | } ;
48 |
49 | /*
50 | r = a * A + b * B
51 | where a = a[0]+256*a[1]+...+256^31 a[31].
52 | and b = b[0]+256*b[1]+...+256^31 b[31].
53 | B is the Ed25519 base point (x,4/5) with x positive.
54 | */
55 |
56 | void ge_double_scalarmult_vartime(ge_p2 *r,const unsigned char *a,const ge_p3 *A,const unsigned char *b)
57 | {
58 | signed char aslide[256];
59 | signed char bslide[256];
60 | ge_cached Ai[8]; /* A,3A,5A,7A,9A,11A,13A,15A */
61 | ge_p1p1 t;
62 | ge_p3 u;
63 | ge_p3 A2;
64 | int i;
65 |
66 | slide(aslide,a);
67 | slide(bslide,b);
68 |
69 | ge_p3_to_cached(&Ai[0],A);
70 | ge_p3_dbl(&t,A); ge_p1p1_to_p3(&A2,&t);
71 | ge_add(&t,&A2,&Ai[0]); ge_p1p1_to_p3(&u,&t); ge_p3_to_cached(&Ai[1],&u);
72 | ge_add(&t,&A2,&Ai[1]); ge_p1p1_to_p3(&u,&t); ge_p3_to_cached(&Ai[2],&u);
73 | ge_add(&t,&A2,&Ai[2]); ge_p1p1_to_p3(&u,&t); ge_p3_to_cached(&Ai[3],&u);
74 | ge_add(&t,&A2,&Ai[3]); ge_p1p1_to_p3(&u,&t); ge_p3_to_cached(&Ai[4],&u);
75 | ge_add(&t,&A2,&Ai[4]); ge_p1p1_to_p3(&u,&t); ge_p3_to_cached(&Ai[5],&u);
76 | ge_add(&t,&A2,&Ai[5]); ge_p1p1_to_p3(&u,&t); ge_p3_to_cached(&Ai[6],&u);
77 | ge_add(&t,&A2,&Ai[6]); ge_p1p1_to_p3(&u,&t); ge_p3_to_cached(&Ai[7],&u);
78 |
79 | ge_p2_0(r);
80 |
81 | for (i = 255;i >= 0;--i) {
82 | if (aslide[i] || bslide[i]) break;
83 | }
84 |
85 | for (;i >= 0;--i) {
86 | ge_p2_dbl(&t,r);
87 |
88 | if (aslide[i] > 0) {
89 | ge_p1p1_to_p3(&u,&t);
90 | ge_add(&t,&u,&Ai[aslide[i]/2]);
91 | } else if (aslide[i] < 0) {
92 | ge_p1p1_to_p3(&u,&t);
93 | ge_sub(&t,&u,&Ai[(-aslide[i])/2]);
94 | }
95 |
96 | if (bslide[i] > 0) {
97 | ge_p1p1_to_p3(&u,&t);
98 | ge_madd(&t,&u,&Bi[bslide[i]/2]);
99 | } else if (bslide[i] < 0) {
100 | ge_p1p1_to_p3(&u,&t);
101 | ge_msub(&t,&u,&Bi[(-bslide[i])/2]);
102 | }
103 |
104 | ge_p1p1_to_p2(r,&t);
105 | }
106 | }
107 |
108 | static const fe d = {
109 | #include "d.h"
110 | } ;
111 |
112 | static const fe sqrtm1 = {
113 | #include "sqrtm1.h"
114 | } ;
115 |
116 | int ge_frombytes_negate_vartime(ge_p3 *h,const unsigned char *s)
117 | {
118 | fe u;
119 | fe v;
120 | fe v3;
121 | fe vxx;
122 | fe check;
123 |
124 | fe_frombytes(h->Y,s);
125 | fe_1(h->Z);
126 | fe_sq(u,h->Y);
127 | fe_mul(v,u,d);
128 | fe_sub(u,u,h->Z); /* u = y^2-1 */
129 | fe_add(v,v,h->Z); /* v = dy^2+1 */
130 |
131 | fe_sq(v3,v);
132 | fe_mul(v3,v3,v); /* v3 = v^3 */
133 | fe_sq(h->X,v3);
134 | fe_mul(h->X,h->X,v);
135 | fe_mul(h->X,h->X,u); /* x = uv^7 */
136 |
137 | fe_pow22523(h->X,h->X); /* x = (uv^7)^((q-5)/8) */
138 | fe_mul(h->X,h->X,v3);
139 | fe_mul(h->X,h->X,u); /* x = uv^3(uv^7)^((q-5)/8) */
140 |
141 | fe_sq(vxx,h->X);
142 | fe_mul(vxx,vxx,v);
143 | fe_sub(check,vxx,u); /* vx^2-u */
144 | if (fe_isnonzero(check)) {
145 | fe_add(check,vxx,u); /* vx^2+u */
146 | if (fe_isnonzero(check)) return -1;
147 | fe_mul(h->X,h->X,sqrtm1);
148 | }
149 |
150 | if (fe_isnegative(h->X) == (s[31] >> 7))
151 | fe_neg(h->X,h->X);
152 |
153 | fe_mul(h->T,h->X,h->Y);
154 | return 0;
155 | }
156 |
157 | /*
158 | r = p + q
159 | */
160 |
161 | void ge_madd(ge_p1p1 *r,const ge_p3 *p,const ge_precomp *q)
162 | {
163 | fe t0;
164 | #include "ge_madd.h"
165 | }
166 |
167 | /*
168 | r = p - q
169 | */
170 |
171 | void ge_msub(ge_p1p1 *r,const ge_p3 *p,const ge_precomp *q)
172 | {
173 | fe t0;
174 | #include "ge_msub.h"
175 | }
176 |
177 | /*
178 | r = p
179 | */
180 |
181 | extern void ge_p1p1_to_p2(ge_p2 *r,const ge_p1p1 *p)
182 | {
183 | fe_mul(r->X,p->X,p->T);
184 | fe_mul(r->Y,p->Y,p->Z);
185 | fe_mul(r->Z,p->Z,p->T);
186 | }
187 |
188 | /*
189 | r = p
190 | */
191 |
192 | extern void ge_p1p1_to_p3(ge_p3 *r,const ge_p1p1 *p)
193 | {
194 | fe_mul(r->X,p->X,p->T);
195 | fe_mul(r->Y,p->Y,p->Z);
196 | fe_mul(r->Z,p->Z,p->T);
197 | fe_mul(r->T,p->X,p->Y);
198 | }
199 |
200 | void ge_p2_0(ge_p2 *h)
201 | {
202 | fe_0(h->X);
203 | fe_1(h->Y);
204 | fe_1(h->Z);
205 | }
206 |
207 | /*
208 | r = 2 * p
209 | */
210 |
211 | void ge_p2_dbl(ge_p1p1 *r,const ge_p2 *p)
212 | {
213 | fe t0;
214 | #include "ge_p2_dbl.h"
215 | }
216 |
217 | void ge_p3_0(ge_p3 *h)
218 | {
219 | fe_0(h->X);
220 | fe_1(h->Y);
221 | fe_1(h->Z);
222 | fe_0(h->T);
223 | }
224 |
225 | /*
226 | r = 2 * p
227 | */
228 |
229 | void ge_p3_dbl(ge_p1p1 *r,const ge_p3 *p)
230 | {
231 | ge_p2 q;
232 | ge_p3_to_p2(&q,p);
233 | ge_p2_dbl(r,&q);
234 | }
235 |
236 | /*
237 | r = p
238 | */
239 |
240 | static const fe d2 = {
241 | #include "d2.h"
242 | } ;
243 |
244 | extern void ge_p3_to_cached(ge_cached *r,const ge_p3 *p)
245 | {
246 | fe_add(r->YplusX,p->Y,p->X);
247 | fe_sub(r->YminusX,p->Y,p->X);
248 | fe_copy(r->Z,p->Z);
249 | fe_mul(r->T2d,p->T,d2);
250 | }
251 |
252 | /*
253 | r = p
254 | */
255 |
256 | extern void ge_p3_to_p2(ge_p2 *r,const ge_p3 *p)
257 | {
258 | fe_copy(r->X,p->X);
259 | fe_copy(r->Y,p->Y);
260 | fe_copy(r->Z,p->Z);
261 | }
262 |
263 | void ge_p3_tobytes(unsigned char *s,const ge_p3 *h)
264 | {
265 | fe recip;
266 | fe x;
267 | fe y;
268 |
269 | fe_invert(recip,h->Z);
270 | fe_mul(x,h->X,recip);
271 | fe_mul(y,h->Y,recip);
272 | fe_tobytes(s,y);
273 | s[31] ^= fe_isnegative(x) << 7;
274 | }
275 |
276 | void ge_precomp_0(ge_precomp *h)
277 | {
278 | fe_1(h->yplusx);
279 | fe_1(h->yminusx);
280 | fe_0(h->xy2d);
281 | }
282 |
283 | static uint8_t equal(int8_t b,int8_t c)
284 | {
285 | uint8_t ub = b;
286 | uint8_t uc = c;
287 | uint8_t x = ub ^ uc; /* 0: yes; 1..255: no */
288 | uint32_t y = x; /* 0: yes; 1..255: no */
289 | y -= 1; /* 4294967295: yes; 0..254: no */
290 | y >>= 31; /* 1: yes; 0: no */
291 | return y;
292 | }
293 |
294 | static uint8_t negative(int8_t b)
295 | {
296 | unsigned long long x = b; /* 18446744073709551361..18446744073709551615: yes; 0..255: no */
297 | x >>= 63; /* 1: yes; 0: no */
298 | return x;
299 | }
300 |
301 | static void cmov(ge_precomp *t,ge_precomp *u,int8_t b)
302 | {
303 | fe_cmov(t->yplusx,u->yplusx,b);
304 | fe_cmov(t->yminusx,u->yminusx,b);
305 | fe_cmov(t->xy2d,u->xy2d,b);
306 | }
307 |
308 | /* base[i][j] = (j+1)*256^i*B */
309 | static ge_precomp base[32][8] = {
310 | #include "base.h"
311 | } ;
312 |
313 | static void select(ge_precomp *t,int pos,int8_t b)
314 | {
315 | ge_precomp minust;
316 | uint8_t bnegative = negative(b);
317 | uint8_t babs = b - (((-bnegative) & b) << 1);
318 |
319 | ge_precomp_0(t);
320 | cmov(t,&base[pos][0],equal(babs,1));
321 | cmov(t,&base[pos][1],equal(babs,2));
322 | cmov(t,&base[pos][2],equal(babs,3));
323 | cmov(t,&base[pos][3],equal(babs,4));
324 | cmov(t,&base[pos][4],equal(babs,5));
325 | cmov(t,&base[pos][5],equal(babs,6));
326 | cmov(t,&base[pos][6],equal(babs,7));
327 | cmov(t,&base[pos][7],equal(babs,8));
328 | fe_copy(minust.yplusx,t->yminusx);
329 | fe_copy(minust.yminusx,t->yplusx);
330 | fe_neg(minust.xy2d,t->xy2d);
331 | cmov(t,&minust,bnegative);
332 | }
333 |
334 | /*
335 | h = a * B
336 | where a = a[0]+256*a[1]+...+256^31 a[31]
337 | B is the Ed25519 base point (x,4/5) with x positive.
338 |
339 | Preconditions:
340 | a[31] <= 127
341 | */
342 |
343 | void ge_scalarmult_base(ge_p3 *h,const uint8_t *a)
344 | {
345 | int8_t e[64];
346 | int8_t carry;
347 | ge_p1p1 r;
348 | ge_p2 s;
349 | ge_precomp t;
350 | int i;
351 |
352 | for (i = 0;i < 32;++i) {
353 | e[2 * i + 0] = (a[i] >> 0) & 15;
354 | e[2 * i + 1] = (a[i] >> 4) & 15;
355 | }
356 | /* each e[i] is between 0 and 15 */
357 | /* e[63] is between 0 and 7 */
358 |
359 | carry = 0;
360 | for (i = 0;i < 63;++i) {
361 | e[i] += carry;
362 | carry = e[i] + 8;
363 | carry >>= 4;
364 | e[i] -= carry << 4;
365 | }
366 | e[63] += carry;
367 | /* each e[i] is between -8 and 8 */
368 |
369 | ge_p3_0(h);
370 | for (i = 1;i < 64;i += 2) {
371 | select(&t,i / 2,e[i]);
372 | ge_madd(&r,h,&t); ge_p1p1_to_p3(h,&r);
373 | }
374 |
375 | ge_p3_dbl(&r,h); ge_p1p1_to_p2(&s,&r);
376 | ge_p2_dbl(&r,&s); ge_p1p1_to_p2(&s,&r);
377 | ge_p2_dbl(&r,&s); ge_p1p1_to_p2(&s,&r);
378 | ge_p2_dbl(&r,&s); ge_p1p1_to_p3(h,&r);
379 |
380 | for (i = 0;i < 64;i += 2) {
381 | select(&t,i / 2,e[i]);
382 | ge_madd(&r,h,&t); ge_p1p1_to_p3(h,&r);
383 | }
384 | }
385 |
386 | /*
387 | r = p - q
388 | */
389 |
390 | void ge_sub(ge_p1p1 *r,const ge_p3 *p,const ge_cached *q)
391 | {
392 | fe t0;
393 | #include "ge_sub.h"
394 | }
395 |
396 | void ge_tobytes(unsigned char *s,const ge_p2 *h)
397 | {
398 | fe recip;
399 | fe x;
400 | fe y;
401 |
402 | fe_invert(recip,h->Z);
403 | fe_mul(x,h->X,recip);
404 | fe_mul(y,h->Y,recip);
405 | fe_tobytes(s,y);
406 | s[31] ^= fe_isnegative(x) << 7;
407 | }
408 |
--------------------------------------------------------------------------------
/ext/ed25519_ref10/ge.h:
--------------------------------------------------------------------------------
1 | #ifndef GE_H
2 | #define GE_H
3 |
4 | /*
5 | ge means group element.
6 |
7 | Here the group is the set of pairs (x,y) of field elements (see fe.h)
8 | satisfying -x^2 + y^2 = 1 + d x^2y^2
9 | where d = -121665/121666.
10 |
11 | Representations:
12 | ge_p2 (projective): (X:Y:Z) satisfying x=X/Z, y=Y/Z
13 | ge_p3 (extended): (X:Y:Z:T) satisfying x=X/Z, y=Y/Z, XY=ZT
14 | ge_p1p1 (completed): ((X:Z),(Y:T)) satisfying x=X/Z, y=Y/T
15 | ge_precomp (Duif): (y+x,y-x,2dxy)
16 | */
17 |
18 | #include "fe.h"
19 |
20 | typedef struct {
21 | fe X;
22 | fe Y;
23 | fe Z;
24 | } ge_p2;
25 |
26 | typedef struct {
27 | fe X;
28 | fe Y;
29 | fe Z;
30 | fe T;
31 | } ge_p3;
32 |
33 | typedef struct {
34 | fe X;
35 | fe Y;
36 | fe Z;
37 | fe T;
38 | } ge_p1p1;
39 |
40 | typedef struct {
41 | fe yplusx;
42 | fe yminusx;
43 | fe xy2d;
44 | } ge_precomp;
45 |
46 | typedef struct {
47 | fe YplusX;
48 | fe YminusX;
49 | fe Z;
50 | fe T2d;
51 | } ge_cached;
52 |
53 | #define ge_frombytes_negate_vartime crypto_sign_ed25519_ref10_ge_frombytes_negate_vartime
54 | #define ge_tobytes crypto_sign_ed25519_ref10_ge_tobytes
55 | #define ge_p3_tobytes crypto_sign_ed25519_ref10_ge_p3_tobytes
56 |
57 | #define ge_p2_0 crypto_sign_ed25519_ref10_ge_p2_0
58 | #define ge_p3_0 crypto_sign_ed25519_ref10_ge_p3_0
59 | #define ge_precomp_0 crypto_sign_ed25519_ref10_ge_precomp_0
60 | #define ge_p3_to_p2 crypto_sign_ed25519_ref10_ge_p3_to_p2
61 | #define ge_p3_to_cached crypto_sign_ed25519_ref10_ge_p3_to_cached
62 | #define ge_p1p1_to_p2 crypto_sign_ed25519_ref10_ge_p1p1_to_p2
63 | #define ge_p1p1_to_p3 crypto_sign_ed25519_ref10_ge_p1p1_to_p3
64 | #define ge_p2_dbl crypto_sign_ed25519_ref10_ge_p2_dbl
65 | #define ge_p3_dbl crypto_sign_ed25519_ref10_ge_p3_dbl
66 |
67 | #define ge_madd crypto_sign_ed25519_ref10_ge_madd
68 | #define ge_msub crypto_sign_ed25519_ref10_ge_msub
69 | #define ge_add crypto_sign_ed25519_ref10_ge_add
70 | #define ge_sub crypto_sign_ed25519_ref10_ge_sub
71 | #define ge_scalarmult_base crypto_sign_ed25519_ref10_ge_scalarmult_base
72 | #define ge_double_scalarmult_vartime crypto_sign_ed25519_ref10_ge_double_scalarmult_vartime
73 |
74 | extern void ge_tobytes(unsigned char *,const ge_p2 *);
75 | extern void ge_p3_tobytes(unsigned char *,const ge_p3 *);
76 | extern int ge_frombytes_negate_vartime(ge_p3 *,const unsigned char *);
77 |
78 | extern void ge_p2_0(ge_p2 *);
79 | extern void ge_p3_0(ge_p3 *);
80 | extern void ge_precomp_0(ge_precomp *);
81 | extern void ge_p3_to_p2(ge_p2 *,const ge_p3 *);
82 | extern void ge_p3_to_cached(ge_cached *,const ge_p3 *);
83 | extern void ge_p1p1_to_p2(ge_p2 *,const ge_p1p1 *);
84 | extern void ge_p1p1_to_p3(ge_p3 *,const ge_p1p1 *);
85 | extern void ge_p2_dbl(ge_p1p1 *,const ge_p2 *);
86 | extern void ge_p3_dbl(ge_p1p1 *,const ge_p3 *);
87 |
88 | extern void ge_madd(ge_p1p1 *,const ge_p3 *,const ge_precomp *);
89 | extern void ge_msub(ge_p1p1 *,const ge_p3 *,const ge_precomp *);
90 | extern void ge_add(ge_p1p1 *,const ge_p3 *,const ge_cached *);
91 | extern void ge_sub(ge_p1p1 *,const ge_p3 *,const ge_cached *);
92 | extern void ge_scalarmult_base(ge_p3 *,const unsigned char *);
93 | extern void ge_double_scalarmult_vartime(ge_p2 *,const unsigned char *,const ge_p3 *,const unsigned char *);
94 |
95 | #endif
96 |
--------------------------------------------------------------------------------
/ext/ed25519_ref10/ge_add.h:
--------------------------------------------------------------------------------
1 |
2 | /* qhasm: enter ge_add */
3 |
4 | /* qhasm: fe X1 */
5 |
6 | /* qhasm: fe Y1 */
7 |
8 | /* qhasm: fe Z1 */
9 |
10 | /* qhasm: fe Z2 */
11 |
12 | /* qhasm: fe T1 */
13 |
14 | /* qhasm: fe ZZ */
15 |
16 | /* qhasm: fe YpX2 */
17 |
18 | /* qhasm: fe YmX2 */
19 |
20 | /* qhasm: fe T2d2 */
21 |
22 | /* qhasm: fe X3 */
23 |
24 | /* qhasm: fe Y3 */
25 |
26 | /* qhasm: fe Z3 */
27 |
28 | /* qhasm: fe T3 */
29 |
30 | /* qhasm: fe YpX1 */
31 |
32 | /* qhasm: fe YmX1 */
33 |
34 | /* qhasm: fe A */
35 |
36 | /* qhasm: fe B */
37 |
38 | /* qhasm: fe C */
39 |
40 | /* qhasm: fe D */
41 |
42 | /* qhasm: YpX1 = Y1+X1 */
43 | /* asm 1: fe_add(>YpX1=fe#1,YpX1=r->X,Y,X); */
45 | fe_add(r->X,p->Y,p->X);
46 |
47 | /* qhasm: YmX1 = Y1-X1 */
48 | /* asm 1: fe_sub(>YmX1=fe#2,YmX1=r->Y,Y,X); */
50 | fe_sub(r->Y,p->Y,p->X);
51 |
52 | /* qhasm: A = YpX1*YpX2 */
53 | /* asm 1: fe_mul(>A=fe#3,A=r->Z,X,YplusX); */
55 | fe_mul(r->Z,r->X,q->YplusX);
56 |
57 | /* qhasm: B = YmX1*YmX2 */
58 | /* asm 1: fe_mul(>B=fe#2,B=r->Y,Y,YminusX); */
60 | fe_mul(r->Y,r->Y,q->YminusX);
61 |
62 | /* qhasm: C = T2d2*T1 */
63 | /* asm 1: fe_mul(>C=fe#4,C=r->T,T2d,T); */
65 | fe_mul(r->T,q->T2d,p->T);
66 |
67 | /* qhasm: ZZ = Z1*Z2 */
68 | /* asm 1: fe_mul(>ZZ=fe#1,ZZ=r->X,Z,Z); */
70 | fe_mul(r->X,p->Z,q->Z);
71 |
72 | /* qhasm: D = 2*ZZ */
73 | /* asm 1: fe_add(>D=fe#5,D=t0,X,X); */
75 | fe_add(t0,r->X,r->X);
76 |
77 | /* qhasm: X3 = A-B */
78 | /* asm 1: fe_sub(>X3=fe#1,X3=r->X,Z,Y); */
80 | fe_sub(r->X,r->Z,r->Y);
81 |
82 | /* qhasm: Y3 = A+B */
83 | /* asm 1: fe_add(>Y3=fe#2,Y3=r->Y,Z,Y); */
85 | fe_add(r->Y,r->Z,r->Y);
86 |
87 | /* qhasm: Z3 = D+C */
88 | /* asm 1: fe_add(>Z3=fe#3,Z3=r->Z,T); */
90 | fe_add(r->Z,t0,r->T);
91 |
92 | /* qhasm: T3 = D-C */
93 | /* asm 1: fe_sub(>T3=fe#4,T3=r->T,T); */
95 | fe_sub(r->T,t0,r->T);
96 |
97 | /* qhasm: return */
98 |
--------------------------------------------------------------------------------
/ext/ed25519_ref10/ge_madd.h:
--------------------------------------------------------------------------------
1 |
2 | /* qhasm: enter ge_madd */
3 |
4 | /* qhasm: fe X1 */
5 |
6 | /* qhasm: fe Y1 */
7 |
8 | /* qhasm: fe Z1 */
9 |
10 | /* qhasm: fe T1 */
11 |
12 | /* qhasm: fe ypx2 */
13 |
14 | /* qhasm: fe ymx2 */
15 |
16 | /* qhasm: fe xy2d2 */
17 |
18 | /* qhasm: fe X3 */
19 |
20 | /* qhasm: fe Y3 */
21 |
22 | /* qhasm: fe Z3 */
23 |
24 | /* qhasm: fe T3 */
25 |
26 | /* qhasm: fe YpX1 */
27 |
28 | /* qhasm: fe YmX1 */
29 |
30 | /* qhasm: fe A */
31 |
32 | /* qhasm: fe B */
33 |
34 | /* qhasm: fe C */
35 |
36 | /* qhasm: fe D */
37 |
38 | /* qhasm: YpX1 = Y1+X1 */
39 | /* asm 1: fe_add(>YpX1=fe#1,YpX1=r->X,Y,X); */
41 | fe_add(r->X,p->Y,p->X);
42 |
43 | /* qhasm: YmX1 = Y1-X1 */
44 | /* asm 1: fe_sub(>YmX1=fe#2,YmX1=r->Y,Y,X); */
46 | fe_sub(r->Y,p->Y,p->X);
47 |
48 | /* qhasm: A = YpX1*ypx2 */
49 | /* asm 1: fe_mul(>A=fe#3,A=r->Z,X,yplusx); */
51 | fe_mul(r->Z,r->X,q->yplusx);
52 |
53 | /* qhasm: B = YmX1*ymx2 */
54 | /* asm 1: fe_mul(>B=fe#2,B=r->Y,Y,yminusx); */
56 | fe_mul(r->Y,r->Y,q->yminusx);
57 |
58 | /* qhasm: C = xy2d2*T1 */
59 | /* asm 1: fe_mul(>C=fe#4,C=r->T,xy2d,T); */
61 | fe_mul(r->T,q->xy2d,p->T);
62 |
63 | /* qhasm: D = 2*Z1 */
64 | /* asm 1: fe_add(>D=fe#5,D=t0,Z,Z); */
66 | fe_add(t0,p->Z,p->Z);
67 |
68 | /* qhasm: X3 = A-B */
69 | /* asm 1: fe_sub(>X3=fe#1,X3=r->X,Z,Y); */
71 | fe_sub(r->X,r->Z,r->Y);
72 |
73 | /* qhasm: Y3 = A+B */
74 | /* asm 1: fe_add(>Y3=fe#2,Y3=r->Y,Z,Y); */
76 | fe_add(r->Y,r->Z,r->Y);
77 |
78 | /* qhasm: Z3 = D+C */
79 | /* asm 1: fe_add(>Z3=fe#3,Z3=r->Z,T); */
81 | fe_add(r->Z,t0,r->T);
82 |
83 | /* qhasm: T3 = D-C */
84 | /* asm 1: fe_sub(>T3=fe#4,T3=r->T,T); */
86 | fe_sub(r->T,t0,r->T);
87 |
88 | /* qhasm: return */
89 |
--------------------------------------------------------------------------------
/ext/ed25519_ref10/ge_msub.h:
--------------------------------------------------------------------------------
1 |
2 | /* qhasm: enter ge_msub */
3 |
4 | /* qhasm: fe X1 */
5 |
6 | /* qhasm: fe Y1 */
7 |
8 | /* qhasm: fe Z1 */
9 |
10 | /* qhasm: fe T1 */
11 |
12 | /* qhasm: fe ypx2 */
13 |
14 | /* qhasm: fe ymx2 */
15 |
16 | /* qhasm: fe xy2d2 */
17 |
18 | /* qhasm: fe X3 */
19 |
20 | /* qhasm: fe Y3 */
21 |
22 | /* qhasm: fe Z3 */
23 |
24 | /* qhasm: fe T3 */
25 |
26 | /* qhasm: fe YpX1 */
27 |
28 | /* qhasm: fe YmX1 */
29 |
30 | /* qhasm: fe A */
31 |
32 | /* qhasm: fe B */
33 |
34 | /* qhasm: fe C */
35 |
36 | /* qhasm: fe D */
37 |
38 | /* qhasm: YpX1 = Y1+X1 */
39 | /* asm 1: fe_add(>YpX1=fe#1,YpX1=r->X,Y,X); */
41 | fe_add(r->X,p->Y,p->X);
42 |
43 | /* qhasm: YmX1 = Y1-X1 */
44 | /* asm 1: fe_sub(>YmX1=fe#2,YmX1=r->Y,Y,X); */
46 | fe_sub(r->Y,p->Y,p->X);
47 |
48 | /* qhasm: A = YpX1*ymx2 */
49 | /* asm 1: fe_mul(>A=fe#3,A=r->Z,X,yminusx); */
51 | fe_mul(r->Z,r->X,q->yminusx);
52 |
53 | /* qhasm: B = YmX1*ypx2 */
54 | /* asm 1: fe_mul(>B=fe#2,B=r->Y,Y,yplusx); */
56 | fe_mul(r->Y,r->Y,q->yplusx);
57 |
58 | /* qhasm: C = xy2d2*T1 */
59 | /* asm 1: fe_mul(>C=fe#4,C=r->T,xy2d,T); */
61 | fe_mul(r->T,q->xy2d,p->T);
62 |
63 | /* qhasm: D = 2*Z1 */
64 | /* asm 1: fe_add(>D=fe#5,D=t0,Z,Z); */
66 | fe_add(t0,p->Z,p->Z);
67 |
68 | /* qhasm: X3 = A-B */
69 | /* asm 1: fe_sub(>X3=fe#1,X3=r->X,Z,Y); */
71 | fe_sub(r->X,r->Z,r->Y);
72 |
73 | /* qhasm: Y3 = A+B */
74 | /* asm 1: fe_add(>Y3=fe#2,Y3=r->Y,Z,Y); */
76 | fe_add(r->Y,r->Z,r->Y);
77 |
78 | /* qhasm: Z3 = D-C */
79 | /* asm 1: fe_sub(>Z3=fe#3,Z3=r->Z,T); */
81 | fe_sub(r->Z,t0,r->T);
82 |
83 | /* qhasm: T3 = D+C */
84 | /* asm 1: fe_add(>T3=fe#4,T3=r->T,T); */
86 | fe_add(r->T,t0,r->T);
87 |
88 | /* qhasm: return */
89 |
--------------------------------------------------------------------------------
/ext/ed25519_ref10/ge_p2_dbl.h:
--------------------------------------------------------------------------------
1 |
2 | /* qhasm: enter ge_p2_dbl */
3 |
4 | /* qhasm: fe X1 */
5 |
6 | /* qhasm: fe Y1 */
7 |
8 | /* qhasm: fe Z1 */
9 |
10 | /* qhasm: fe A */
11 |
12 | /* qhasm: fe AA */
13 |
14 | /* qhasm: fe XX */
15 |
16 | /* qhasm: fe YY */
17 |
18 | /* qhasm: fe B */
19 |
20 | /* qhasm: fe X3 */
21 |
22 | /* qhasm: fe Y3 */
23 |
24 | /* qhasm: fe Z3 */
25 |
26 | /* qhasm: fe T3 */
27 |
28 | /* qhasm: XX=X1^2 */
29 | /* asm 1: fe_sq(>XX=fe#1,XX=r->X,X); */
31 | fe_sq(r->X,p->X);
32 |
33 | /* qhasm: YY=Y1^2 */
34 | /* asm 1: fe_sq(>YY=fe#3,YY=r->Z,Y); */
36 | fe_sq(r->Z,p->Y);
37 |
38 | /* qhasm: B=2*Z1^2 */
39 | /* asm 1: fe_sq2(>B=fe#4,B=r->T,Z); */
41 | fe_sq2(r->T,p->Z);
42 |
43 | /* qhasm: A=X1+Y1 */
44 | /* asm 1: fe_add(>A=fe#2,A=r->Y,X,Y); */
46 | fe_add(r->Y,p->X,p->Y);
47 |
48 | /* qhasm: AA=A^2 */
49 | /* asm 1: fe_sq(>AA=fe#5,AA=t0,Y); */
51 | fe_sq(t0,r->Y);
52 |
53 | /* qhasm: Y3=YY+XX */
54 | /* asm 1: fe_add(>Y3=fe#2,Y3=r->Y,Z,X); */
56 | fe_add(r->Y,r->Z,r->X);
57 |
58 | /* qhasm: Z3=YY-XX */
59 | /* asm 1: fe_sub(>Z3=fe#3,Z3=r->Z,Z,X); */
61 | fe_sub(r->Z,r->Z,r->X);
62 |
63 | /* qhasm: X3=AA-Y3 */
64 | /* asm 1: fe_sub(>X3=fe#1,X3=r->X,Y); */
66 | fe_sub(r->X,t0,r->Y);
67 |
68 | /* qhasm: T3=B-Z3 */
69 | /* asm 1: fe_sub(>T3=fe#4,T3=r->T,T,Z); */
71 | fe_sub(r->T,r->T,r->Z);
72 |
73 | /* qhasm: return */
74 |
--------------------------------------------------------------------------------
/ext/ed25519_ref10/ge_sub.h:
--------------------------------------------------------------------------------
1 |
2 | /* qhasm: enter ge_sub */
3 |
4 | /* qhasm: fe X1 */
5 |
6 | /* qhasm: fe Y1 */
7 |
8 | /* qhasm: fe Z1 */
9 |
10 | /* qhasm: fe Z2 */
11 |
12 | /* qhasm: fe T1 */
13 |
14 | /* qhasm: fe ZZ */
15 |
16 | /* qhasm: fe YpX2 */
17 |
18 | /* qhasm: fe YmX2 */
19 |
20 | /* qhasm: fe T2d2 */
21 |
22 | /* qhasm: fe X3 */
23 |
24 | /* qhasm: fe Y3 */
25 |
26 | /* qhasm: fe Z3 */
27 |
28 | /* qhasm: fe T3 */
29 |
30 | /* qhasm: fe YpX1 */
31 |
32 | /* qhasm: fe YmX1 */
33 |
34 | /* qhasm: fe A */
35 |
36 | /* qhasm: fe B */
37 |
38 | /* qhasm: fe C */
39 |
40 | /* qhasm: fe D */
41 |
42 | /* qhasm: YpX1 = Y1+X1 */
43 | /* asm 1: fe_add(>YpX1=fe#1,YpX1=r->X,Y,X); */
45 | fe_add(r->X,p->Y,p->X);
46 |
47 | /* qhasm: YmX1 = Y1-X1 */
48 | /* asm 1: fe_sub(>YmX1=fe#2,YmX1=r->Y,Y,X); */
50 | fe_sub(r->Y,p->Y,p->X);
51 |
52 | /* qhasm: A = YpX1*YmX2 */
53 | /* asm 1: fe_mul(>A=fe#3,A=r->Z,X,YminusX); */
55 | fe_mul(r->Z,r->X,q->YminusX);
56 |
57 | /* qhasm: B = YmX1*YpX2 */
58 | /* asm 1: fe_mul(>B=fe#2,B=r->Y,Y,YplusX); */
60 | fe_mul(r->Y,r->Y,q->YplusX);
61 |
62 | /* qhasm: C = T2d2*T1 */
63 | /* asm 1: fe_mul(>C=fe#4,C=r->T,T2d,T); */
65 | fe_mul(r->T,q->T2d,p->T);
66 |
67 | /* qhasm: ZZ = Z1*Z2 */
68 | /* asm 1: fe_mul(>ZZ=fe#1,ZZ=r->X,Z,Z); */
70 | fe_mul(r->X,p->Z,q->Z);
71 |
72 | /* qhasm: D = 2*ZZ */
73 | /* asm 1: fe_add(>D=fe#5,D=t0,X,X); */
75 | fe_add(t0,r->X,r->X);
76 |
77 | /* qhasm: X3 = A-B */
78 | /* asm 1: fe_sub(>X3=fe#1,X3=r->X,Z,Y); */
80 | fe_sub(r->X,r->Z,r->Y);
81 |
82 | /* qhasm: Y3 = A+B */
83 | /* asm 1: fe_add(>Y3=fe#2,Y3=r->Y,Z,Y); */
85 | fe_add(r->Y,r->Z,r->Y);
86 |
87 | /* qhasm: Z3 = D-C */
88 | /* asm 1: fe_sub(>Z3=fe#3,Z3=r->Z,T); */
90 | fe_sub(r->Z,t0,r->T);
91 |
92 | /* qhasm: T3 = D+C */
93 | /* asm 1: fe_add(>T3=fe#4,T3=r->T,T); */
95 | fe_add(r->T,t0,r->T);
96 |
97 | /* qhasm: return */
98 |
--------------------------------------------------------------------------------
/ext/ed25519_ref10/keypair.c:
--------------------------------------------------------------------------------
1 | #include
2 | #include "ed25519_ref10.h"
3 | #include "sha512.h"
4 | #include "ge.h"
5 |
6 | int crypto_sign_ed25519_ref10_seed_keypair(uint8_t *pk, uint8_t *sk, const uint8_t *seed)
7 | {
8 | ge_p3 A;
9 |
10 | crypto_hash_sha512(sk, seed, 32);
11 | sk[0] &= 248;
12 | sk[31] &= 127;
13 | sk[31] |= 64;
14 |
15 | ge_scalarmult_base(&A, sk);
16 | ge_p3_tobytes(pk, &A);
17 |
18 | memmove(sk, seed, 32);
19 | memmove(sk + 32, pk, 32);
20 |
21 | return 0;
22 | }
23 |
--------------------------------------------------------------------------------
/ext/ed25519_ref10/open.c:
--------------------------------------------------------------------------------
1 | #include
2 | #include "sha512.h"
3 | #include "ed25519_ref10.h"
4 | #include "ge.h"
5 | #include "sc.h"
6 |
7 | int crypto_sign_open_ed25519_ref10(
8 | uint8_t *m, uint64_t *mlen,
9 | const uint8_t *sm, uint64_t smlen,
10 | const uint8_t *pk
11 | )
12 | {
13 | unsigned char pkcopy[32];
14 | unsigned char rcopy[32];
15 | unsigned char scopy[32];
16 | unsigned char h[64];
17 | unsigned char rcheck[32];
18 | ge_p3 A;
19 | ge_p2 R;
20 |
21 | if (smlen < 64) goto badsig;
22 | if (sm[63] & 224) goto badsig;
23 | if (ge_frombytes_negate_vartime(&A,pk) != 0) goto badsig;
24 |
25 | memmove(pkcopy,pk,32);
26 | memmove(rcopy,sm,32);
27 | memmove(scopy,sm + 32,32);
28 |
29 | memmove(m,sm,smlen);
30 | memmove(m + 32,pkcopy,32);
31 | crypto_hash_sha512(h,m,smlen);
32 | sc_reduce(h);
33 |
34 | ge_double_scalarmult_vartime(&R,h,&A,scopy);
35 | ge_tobytes(rcheck,&R);
36 | if (crypto_verify_32(rcheck,rcopy) == 0) {
37 | memmove(m,m + 64,smlen - 64);
38 | memset(m + smlen - 64,0,64);
39 | *mlen = smlen - 64;
40 | return 0;
41 | }
42 |
43 | badsig:
44 | *mlen = -1;
45 | memset(m,0,smlen);
46 | return -1;
47 | }
48 |
--------------------------------------------------------------------------------
/ext/ed25519_ref10/pow22523.h:
--------------------------------------------------------------------------------
1 |
2 | /* qhasm: fe z1 */
3 |
4 | /* qhasm: fe z2 */
5 |
6 | /* qhasm: fe z8 */
7 |
8 | /* qhasm: fe z9 */
9 |
10 | /* qhasm: fe z11 */
11 |
12 | /* qhasm: fe z22 */
13 |
14 | /* qhasm: fe z_5_0 */
15 |
16 | /* qhasm: fe z_10_5 */
17 |
18 | /* qhasm: fe z_10_0 */
19 |
20 | /* qhasm: fe z_20_10 */
21 |
22 | /* qhasm: fe z_20_0 */
23 |
24 | /* qhasm: fe z_40_20 */
25 |
26 | /* qhasm: fe z_40_0 */
27 |
28 | /* qhasm: fe z_50_10 */
29 |
30 | /* qhasm: fe z_50_0 */
31 |
32 | /* qhasm: fe z_100_50 */
33 |
34 | /* qhasm: fe z_100_0 */
35 |
36 | /* qhasm: fe z_200_100 */
37 |
38 | /* qhasm: fe z_200_0 */
39 |
40 | /* qhasm: fe z_250_50 */
41 |
42 | /* qhasm: fe z_250_0 */
43 |
44 | /* qhasm: fe z_252_2 */
45 |
46 | /* qhasm: fe z_252_3 */
47 |
48 | /* qhasm: enter pow22523 */
49 |
50 | /* qhasm: z2 = z1^2^1 */
51 | /* asm 1: fe_sq(>z2=fe#1,z2=fe#1,>z2=fe#1); */
52 | /* asm 2: fe_sq(>z2=t0,z2=t0,>z2=t0); */
53 | fe_sq(t0,z); for (i = 1;i < 1;++i) fe_sq(t0,t0);
54 |
55 | /* qhasm: z8 = z2^2^2 */
56 | /* asm 1: fe_sq(>z8=fe#2,z8=fe#2,>z8=fe#2); */
57 | /* asm 2: fe_sq(>z8=t1,z8=t1,>z8=t1); */
58 | fe_sq(t1,t0); for (i = 1;i < 2;++i) fe_sq(t1,t1);
59 |
60 | /* qhasm: z9 = z1*z8 */
61 | /* asm 1: fe_mul(>z9=fe#2,z9=t1,z11=fe#1,z11=t0,z22=fe#1,z22=fe#1,>z22=fe#1); */
72 | /* asm 2: fe_sq(>z22=t0,z22=t0,>z22=t0); */
73 | fe_sq(t0,t0); for (i = 1;i < 1;++i) fe_sq(t0,t0);
74 |
75 | /* qhasm: z_5_0 = z9*z22 */
76 | /* asm 1: fe_mul(>z_5_0=fe#1,z_5_0=t0,z_10_5=fe#2,z_10_5=fe#2,>z_10_5=fe#2); */
82 | /* asm 2: fe_sq(>z_10_5=t1,z_10_5=t1,>z_10_5=t1); */
83 | fe_sq(t1,t0); for (i = 1;i < 5;++i) fe_sq(t1,t1);
84 |
85 | /* qhasm: z_10_0 = z_10_5*z_5_0 */
86 | /* asm 1: fe_mul(>z_10_0=fe#1,z_10_0=t0,z_20_10=fe#2,z_20_10=fe#2,>z_20_10=fe#2); */
92 | /* asm 2: fe_sq(>z_20_10=t1,z_20_10=t1,>z_20_10=t1); */
93 | fe_sq(t1,t0); for (i = 1;i < 10;++i) fe_sq(t1,t1);
94 |
95 | /* qhasm: z_20_0 = z_20_10*z_10_0 */
96 | /* asm 1: fe_mul(>z_20_0=fe#2,z_20_0=t1,z_40_20=fe#3,z_40_20=fe#3,>z_40_20=fe#3); */
102 | /* asm 2: fe_sq(>z_40_20=t2,z_40_20=t2,>z_40_20=t2); */
103 | fe_sq(t2,t1); for (i = 1;i < 20;++i) fe_sq(t2,t2);
104 |
105 | /* qhasm: z_40_0 = z_40_20*z_20_0 */
106 | /* asm 1: fe_mul(>z_40_0=fe#2,z_40_0=t1,z_50_10=fe#2,z_50_10=fe#2,>z_50_10=fe#2); */
112 | /* asm 2: fe_sq(>z_50_10=t1,z_50_10=t1,>z_50_10=t1); */
113 | fe_sq(t1,t1); for (i = 1;i < 10;++i) fe_sq(t1,t1);
114 |
115 | /* qhasm: z_50_0 = z_50_10*z_10_0 */
116 | /* asm 1: fe_mul(>z_50_0=fe#1,z_50_0=t0,z_100_50=fe#2,z_100_50=fe#2,>z_100_50=fe#2); */
122 | /* asm 2: fe_sq(>z_100_50=t1,z_100_50=t1,>z_100_50=t1); */
123 | fe_sq(t1,t0); for (i = 1;i < 50;++i) fe_sq(t1,t1);
124 |
125 | /* qhasm: z_100_0 = z_100_50*z_50_0 */
126 | /* asm 1: fe_mul(>z_100_0=fe#2,z_100_0=t1,z_200_100=fe#3,z_200_100=fe#3,>z_200_100=fe#3); */
132 | /* asm 2: fe_sq(>z_200_100=t2,z_200_100=t2,>z_200_100=t2); */
133 | fe_sq(t2,t1); for (i = 1;i < 100;++i) fe_sq(t2,t2);
134 |
135 | /* qhasm: z_200_0 = z_200_100*z_100_0 */
136 | /* asm 1: fe_mul(>z_200_0=fe#2,z_200_0=t1,z_250_50=fe#2,z_250_50=fe#2,>z_250_50=fe#2); */
142 | /* asm 2: fe_sq(>z_250_50=t1,z_250_50=t1,>z_250_50=t1); */
143 | fe_sq(t1,t1); for (i = 1;i < 50;++i) fe_sq(t1,t1);
144 |
145 | /* qhasm: z_250_0 = z_250_50*z_50_0 */
146 | /* asm 1: fe_mul(>z_250_0=fe#1,z_250_0=t0,z_252_2=fe#1,z_252_2=fe#1,>z_252_2=fe#1); */
152 | /* asm 2: fe_sq(>z_252_2=t0,z_252_2=t0,>z_252_2=t0); */
153 | fe_sq(t0,t0); for (i = 1;i < 2;++i) fe_sq(t0,t0);
154 |
155 | /* qhasm: z_252_3 = z_252_2*z1 */
156 | /* asm 1: fe_mul(>z_252_3=fe#12,z_252_3=out,z2=fe#1,z2=fe#1,>z2=fe#1); */
52 | /* asm 2: fe_sq(>z2=t0,z2=t0,>z2=t0); */
53 | fe_sq(t0,z); for (i = 1;i < 1;++i) fe_sq(t0,t0);
54 |
55 | /* qhasm: z8 = z2^2^2 */
56 | /* asm 1: fe_sq(>z8=fe#2,z8=fe#2,>z8=fe#2); */
57 | /* asm 2: fe_sq(>z8=t1,z8=t1,>z8=t1); */
58 | fe_sq(t1,t0); for (i = 1;i < 2;++i) fe_sq(t1,t1);
59 |
60 | /* qhasm: z9 = z1*z8 */
61 | /* asm 1: fe_mul(>z9=fe#2,z9=t1,z11=fe#1,z11=t0,z22=fe#3,z22=fe#3,>z22=fe#3); */
72 | /* asm 2: fe_sq(>z22=t2,z22=t2,>z22=t2); */
73 | fe_sq(t2,t0); for (i = 1;i < 1;++i) fe_sq(t2,t2);
74 |
75 | /* qhasm: z_5_0 = z9*z22 */
76 | /* asm 1: fe_mul(>z_5_0=fe#2,z_5_0=t1,z_10_5=fe#3,z_10_5=fe#3,>z_10_5=fe#3); */
82 | /* asm 2: fe_sq(>z_10_5=t2,z_10_5=t2,>z_10_5=t2); */
83 | fe_sq(t2,t1); for (i = 1;i < 5;++i) fe_sq(t2,t2);
84 |
85 | /* qhasm: z_10_0 = z_10_5*z_5_0 */
86 | /* asm 1: fe_mul(>z_10_0=fe#2,z_10_0=t1,z_20_10=fe#3,z_20_10=fe#3,>z_20_10=fe#3); */
92 | /* asm 2: fe_sq(>z_20_10=t2,z_20_10=t2,>z_20_10=t2); */
93 | fe_sq(t2,t1); for (i = 1;i < 10;++i) fe_sq(t2,t2);
94 |
95 | /* qhasm: z_20_0 = z_20_10*z_10_0 */
96 | /* asm 1: fe_mul(>z_20_0=fe#3,z_20_0=t2,z_40_20=fe#4,z_40_20=fe#4,>z_40_20=fe#4); */
102 | /* asm 2: fe_sq(>z_40_20=t3,z_40_20=t3,>z_40_20=t3); */
103 | fe_sq(t3,t2); for (i = 1;i < 20;++i) fe_sq(t3,t3);
104 |
105 | /* qhasm: z_40_0 = z_40_20*z_20_0 */
106 | /* asm 1: fe_mul(>z_40_0=fe#3,z_40_0=t2,z_50_10=fe#3,z_50_10=fe#3,>z_50_10=fe#3); */
112 | /* asm 2: fe_sq(>z_50_10=t2,z_50_10=t2,>z_50_10=t2); */
113 | fe_sq(t2,t2); for (i = 1;i < 10;++i) fe_sq(t2,t2);
114 |
115 | /* qhasm: z_50_0 = z_50_10*z_10_0 */
116 | /* asm 1: fe_mul(>z_50_0=fe#2,z_50_0=t1,z_100_50=fe#3,z_100_50=fe#3,>z_100_50=fe#3); */
122 | /* asm 2: fe_sq(>z_100_50=t2,z_100_50=t2,>z_100_50=t2); */
123 | fe_sq(t2,t1); for (i = 1;i < 50;++i) fe_sq(t2,t2);
124 |
125 | /* qhasm: z_100_0 = z_100_50*z_50_0 */
126 | /* asm 1: fe_mul(>z_100_0=fe#3,z_100_0=t2,z_200_100=fe#4,z_200_100=fe#4,>z_200_100=fe#4); */
132 | /* asm 2: fe_sq(>z_200_100=t3,z_200_100=t3,>z_200_100=t3); */
133 | fe_sq(t3,t2); for (i = 1;i < 100;++i) fe_sq(t3,t3);
134 |
135 | /* qhasm: z_200_0 = z_200_100*z_100_0 */
136 | /* asm 1: fe_mul(>z_200_0=fe#3,z_200_0=t2,z_250_50=fe#3,z_250_50=fe#3,>z_250_50=fe#3); */
142 | /* asm 2: fe_sq(>z_250_50=t2,z_250_50=t2,>z_250_50=t2); */
143 | fe_sq(t2,t2); for (i = 1;i < 50;++i) fe_sq(t2,t2);
144 |
145 | /* qhasm: z_250_0 = z_250_50*z_50_0 */
146 | /* asm 1: fe_mul(>z_250_0=fe#2,z_250_0=t1,z_255_5=fe#2,z_255_5=fe#2,>z_255_5=fe#2); */
152 | /* asm 2: fe_sq(>z_255_5=t1,z_255_5=t1,>z_255_5=t1); */
153 | fe_sq(t1,t1); for (i = 1;i < 5;++i) fe_sq(t1,t1);
154 |
155 | /* qhasm: z_255_21 = z_255_5*z11 */
156 | /* asm 1: fe_mul(>z_255_21=fe#12,z_255_21=out,
5 |
6 | /*
7 | The set of scalars is \Z/l
8 | where l = 2^252 + 27742317777372353535851937790883648493.
9 | */
10 |
11 | #define sc_reduce crypto_sign_ed25519_ref10_sc_reduce
12 | #define sc_muladd crypto_sign_ed25519_ref10_sc_muladd
13 |
14 | extern void sc_reduce(uint8_t *);
15 | extern void sc_muladd(uint8_t *,const uint8_t *,const uint8_t *,const uint8_t *);
16 |
17 | #endif
18 |
--------------------------------------------------------------------------------
/ext/ed25519_ref10/sc_muladd.c:
--------------------------------------------------------------------------------
1 | #include "sc.h"
2 |
3 | static uint64_t load_3(const uint8_t *in)
4 | {
5 | uint64_t result;
6 | result = (uint64_t) in[0];
7 | result |= ((uint64_t) in[1]) << 8;
8 | result |= ((uint64_t) in[2]) << 16;
9 | return result;
10 | }
11 |
12 | static uint64_t load_4(const uint8_t *in)
13 | {
14 | uint64_t result;
15 | result = (uint64_t) in[0];
16 | result |= ((uint64_t) in[1]) << 8;
17 | result |= ((uint64_t) in[2]) << 16;
18 | result |= ((uint64_t) in[3]) << 24;
19 | return result;
20 | }
21 |
22 | /*
23 | Input:
24 | a[0]+256*a[1]+...+256^31*a[31] = a
25 | b[0]+256*b[1]+...+256^31*b[31] = b
26 | c[0]+256*c[1]+...+256^31*c[31] = c
27 |
28 | Output:
29 | s[0]+256*s[1]+...+256^31*s[31] = (ab+c) mod l
30 | where l = 2^252 + 27742317777372353535851937790883648493.
31 | */
32 |
33 | void sc_muladd(uint8_t *s,const uint8_t *a,const uint8_t *b,const uint8_t *c)
34 | {
35 | int64_t a0 = 2097151 & load_3(a);
36 | int64_t a1 = 2097151 & (load_4(a + 2) >> 5);
37 | int64_t a2 = 2097151 & (load_3(a + 5) >> 2);
38 | int64_t a3 = 2097151 & (load_4(a + 7) >> 7);
39 | int64_t a4 = 2097151 & (load_4(a + 10) >> 4);
40 | int64_t a5 = 2097151 & (load_3(a + 13) >> 1);
41 | int64_t a6 = 2097151 & (load_4(a + 15) >> 6);
42 | int64_t a7 = 2097151 & (load_3(a + 18) >> 3);
43 | int64_t a8 = 2097151 & load_3(a + 21);
44 | int64_t a9 = 2097151 & (load_4(a + 23) >> 5);
45 | int64_t a10 = 2097151 & (load_3(a + 26) >> 2);
46 | int64_t a11 = (load_4(a + 28) >> 7);
47 | int64_t b0 = 2097151 & load_3(b);
48 | int64_t b1 = 2097151 & (load_4(b + 2) >> 5);
49 | int64_t b2 = 2097151 & (load_3(b + 5) >> 2);
50 | int64_t b3 = 2097151 & (load_4(b + 7) >> 7);
51 | int64_t b4 = 2097151 & (load_4(b + 10) >> 4);
52 | int64_t b5 = 2097151 & (load_3(b + 13) >> 1);
53 | int64_t b6 = 2097151 & (load_4(b + 15) >> 6);
54 | int64_t b7 = 2097151 & (load_3(b + 18) >> 3);
55 | int64_t b8 = 2097151 & load_3(b + 21);
56 | int64_t b9 = 2097151 & (load_4(b + 23) >> 5);
57 | int64_t b10 = 2097151 & (load_3(b + 26) >> 2);
58 | int64_t b11 = (load_4(b + 28) >> 7);
59 | int64_t c0 = 2097151 & load_3(c);
60 | int64_t c1 = 2097151 & (load_4(c + 2) >> 5);
61 | int64_t c2 = 2097151 & (load_3(c + 5) >> 2);
62 | int64_t c3 = 2097151 & (load_4(c + 7) >> 7);
63 | int64_t c4 = 2097151 & (load_4(c + 10) >> 4);
64 | int64_t c5 = 2097151 & (load_3(c + 13) >> 1);
65 | int64_t c6 = 2097151 & (load_4(c + 15) >> 6);
66 | int64_t c7 = 2097151 & (load_3(c + 18) >> 3);
67 | int64_t c8 = 2097151 & load_3(c + 21);
68 | int64_t c9 = 2097151 & (load_4(c + 23) >> 5);
69 | int64_t c10 = 2097151 & (load_3(c + 26) >> 2);
70 | int64_t c11 = (load_4(c + 28) >> 7);
71 | int64_t s0;
72 | int64_t s1;
73 | int64_t s2;
74 | int64_t s3;
75 | int64_t s4;
76 | int64_t s5;
77 | int64_t s6;
78 | int64_t s7;
79 | int64_t s8;
80 | int64_t s9;
81 | int64_t s10;
82 | int64_t s11;
83 | int64_t s12;
84 | int64_t s13;
85 | int64_t s14;
86 | int64_t s15;
87 | int64_t s16;
88 | int64_t s17;
89 | int64_t s18;
90 | int64_t s19;
91 | int64_t s20;
92 | int64_t s21;
93 | int64_t s22;
94 | int64_t s23;
95 | int64_t carry0;
96 | int64_t carry1;
97 | int64_t carry2;
98 | int64_t carry3;
99 | int64_t carry4;
100 | int64_t carry5;
101 | int64_t carry6;
102 | int64_t carry7;
103 | int64_t carry8;
104 | int64_t carry9;
105 | int64_t carry10;
106 | int64_t carry11;
107 | int64_t carry12;
108 | int64_t carry13;
109 | int64_t carry14;
110 | int64_t carry15;
111 | int64_t carry16;
112 | int64_t carry17;
113 | int64_t carry18;
114 | int64_t carry19;
115 | int64_t carry20;
116 | int64_t carry21;
117 | int64_t carry22;
118 |
119 | /* Merry Christmas! */
120 | s0 = c0 + a0*b0;
121 | s1 = c1 + a0*b1 + a1*b0;
122 | s2 = c2 + a0*b2 + a1*b1 + a2*b0;
123 | s3 = c3 + a0*b3 + a1*b2 + a2*b1 + a3*b0;
124 | s4 = c4 + a0*b4 + a1*b3 + a2*b2 + a3*b1 + a4*b0;
125 | s5 = c5 + a0*b5 + a1*b4 + a2*b3 + a3*b2 + a4*b1 + a5*b0;
126 | s6 = c6 + a0*b6 + a1*b5 + a2*b4 + a3*b3 + a4*b2 + a5*b1 + a6*b0;
127 | s7 = c7 + a0*b7 + a1*b6 + a2*b5 + a3*b4 + a4*b3 + a5*b2 + a6*b1 + a7*b0;
128 | s8 = c8 + a0*b8 + a1*b7 + a2*b6 + a3*b5 + a4*b4 + a5*b3 + a6*b2 + a7*b1 + a8*b0;
129 | s9 = c9 + a0*b9 + a1*b8 + a2*b7 + a3*b6 + a4*b5 + a5*b4 + a6*b3 + a7*b2 + a8*b1 + a9*b0;
130 | s10 = c10 + a0*b10 + a1*b9 + a2*b8 + a3*b7 + a4*b6 + a5*b5 + a6*b4 + a7*b3 + a8*b2 + a9*b1 + a10*b0;
131 | s11 = c11 + a0*b11 + a1*b10 + a2*b9 + a3*b8 + a4*b7 + a5*b6 + a6*b5 + a7*b4 + a8*b3 + a9*b2 + a10*b1 + a11*b0;
132 | s12 = a1*b11 + a2*b10 + a3*b9 + a4*b8 + a5*b7 + a6*b6 + a7*b5 + a8*b4 + a9*b3 + a10*b2 + a11*b1;
133 | s13 = a2*b11 + a3*b10 + a4*b9 + a5*b8 + a6*b7 + a7*b6 + a8*b5 + a9*b4 + a10*b3 + a11*b2;
134 | s14 = a3*b11 + a4*b10 + a5*b9 + a6*b8 + a7*b7 + a8*b6 + a9*b5 + a10*b4 + a11*b3;
135 | s15 = a4*b11 + a5*b10 + a6*b9 + a7*b8 + a8*b7 + a9*b6 + a10*b5 + a11*b4;
136 | s16 = a5*b11 + a6*b10 + a7*b9 + a8*b8 + a9*b7 + a10*b6 + a11*b5;
137 | s17 = a6*b11 + a7*b10 + a8*b9 + a9*b8 + a10*b7 + a11*b6;
138 | s18 = a7*b11 + a8*b10 + a9*b9 + a10*b8 + a11*b7;
139 | s19 = a8*b11 + a9*b10 + a10*b9 + a11*b8;
140 | s20 = a9*b11 + a10*b10 + a11*b9;
141 | s21 = a10*b11 + a11*b10;
142 | s22 = a11*b11;
143 | s23 = 0;
144 |
145 | carry0 = (s0 + (1<<20)) >> 21; s1 += carry0; s0 -= carry0 << 21;
146 | carry2 = (s2 + (1<<20)) >> 21; s3 += carry2; s2 -= carry2 << 21;
147 | carry4 = (s4 + (1<<20)) >> 21; s5 += carry4; s4 -= carry4 << 21;
148 | carry6 = (s6 + (1<<20)) >> 21; s7 += carry6; s6 -= carry6 << 21;
149 | carry8 = (s8 + (1<<20)) >> 21; s9 += carry8; s8 -= carry8 << 21;
150 | carry10 = (s10 + (1<<20)) >> 21; s11 += carry10; s10 -= carry10 << 21;
151 | carry12 = (s12 + (1<<20)) >> 21; s13 += carry12; s12 -= carry12 << 21;
152 | carry14 = (s14 + (1<<20)) >> 21; s15 += carry14; s14 -= carry14 << 21;
153 | carry16 = (s16 + (1<<20)) >> 21; s17 += carry16; s16 -= carry16 << 21;
154 | carry18 = (s18 + (1<<20)) >> 21; s19 += carry18; s18 -= carry18 << 21;
155 | carry20 = (s20 + (1<<20)) >> 21; s21 += carry20; s20 -= carry20 << 21;
156 | carry22 = (s22 + (1<<20)) >> 21; s23 += carry22; s22 -= carry22 << 21;
157 |
158 | carry1 = (s1 + (1<<20)) >> 21; s2 += carry1; s1 -= carry1 << 21;
159 | carry3 = (s3 + (1<<20)) >> 21; s4 += carry3; s3 -= carry3 << 21;
160 | carry5 = (s5 + (1<<20)) >> 21; s6 += carry5; s5 -= carry5 << 21;
161 | carry7 = (s7 + (1<<20)) >> 21; s8 += carry7; s7 -= carry7 << 21;
162 | carry9 = (s9 + (1<<20)) >> 21; s10 += carry9; s9 -= carry9 << 21;
163 | carry11 = (s11 + (1<<20)) >> 21; s12 += carry11; s11 -= carry11 << 21;
164 | carry13 = (s13 + (1<<20)) >> 21; s14 += carry13; s13 -= carry13 << 21;
165 | carry15 = (s15 + (1<<20)) >> 21; s16 += carry15; s15 -= carry15 << 21;
166 | carry17 = (s17 + (1<<20)) >> 21; s18 += carry17; s17 -= carry17 << 21;
167 | carry19 = (s19 + (1<<20)) >> 21; s20 += carry19; s19 -= carry19 << 21;
168 | carry21 = (s21 + (1<<20)) >> 21; s22 += carry21; s21 -= carry21 << 21;
169 |
170 | s11 += s23 * 666643;
171 | s12 += s23 * 470296;
172 | s13 += s23 * 654183;
173 | s14 -= s23 * 997805;
174 | s15 += s23 * 136657;
175 | s16 -= s23 * 683901;
176 | s23 = 0;
177 |
178 | s10 += s22 * 666643;
179 | s11 += s22 * 470296;
180 | s12 += s22 * 654183;
181 | s13 -= s22 * 997805;
182 | s14 += s22 * 136657;
183 | s15 -= s22 * 683901;
184 | s22 = 0;
185 |
186 | s9 += s21 * 666643;
187 | s10 += s21 * 470296;
188 | s11 += s21 * 654183;
189 | s12 -= s21 * 997805;
190 | s13 += s21 * 136657;
191 | s14 -= s21 * 683901;
192 | s21 = 0;
193 |
194 | s8 += s20 * 666643;
195 | s9 += s20 * 470296;
196 | s10 += s20 * 654183;
197 | s11 -= s20 * 997805;
198 | s12 += s20 * 136657;
199 | s13 -= s20 * 683901;
200 | s20 = 0;
201 |
202 | s7 += s19 * 666643;
203 | s8 += s19 * 470296;
204 | s9 += s19 * 654183;
205 | s10 -= s19 * 997805;
206 | s11 += s19 * 136657;
207 | s12 -= s19 * 683901;
208 | s19 = 0;
209 |
210 | s6 += s18 * 666643;
211 | s7 += s18 * 470296;
212 | s8 += s18 * 654183;
213 | s9 -= s18 * 997805;
214 | s10 += s18 * 136657;
215 | s11 -= s18 * 683901;
216 | s18 = 0;
217 |
218 | carry6 = (s6 + (1<<20)) >> 21; s7 += carry6; s6 -= carry6 << 21;
219 | carry8 = (s8 + (1<<20)) >> 21; s9 += carry8; s8 -= carry8 << 21;
220 | carry10 = (s10 + (1<<20)) >> 21; s11 += carry10; s10 -= carry10 << 21;
221 | carry12 = (s12 + (1<<20)) >> 21; s13 += carry12; s12 -= carry12 << 21;
222 | carry14 = (s14 + (1<<20)) >> 21; s15 += carry14; s14 -= carry14 << 21;
223 | carry16 = (s16 + (1<<20)) >> 21; s17 += carry16; s16 -= carry16 << 21;
224 |
225 | carry7 = (s7 + (1<<20)) >> 21; s8 += carry7; s7 -= carry7 << 21;
226 | carry9 = (s9 + (1<<20)) >> 21; s10 += carry9; s9 -= carry9 << 21;
227 | carry11 = (s11 + (1<<20)) >> 21; s12 += carry11; s11 -= carry11 << 21;
228 | carry13 = (s13 + (1<<20)) >> 21; s14 += carry13; s13 -= carry13 << 21;
229 | carry15 = (s15 + (1<<20)) >> 21; s16 += carry15; s15 -= carry15 << 21;
230 |
231 | s5 += s17 * 666643;
232 | s6 += s17 * 470296;
233 | s7 += s17 * 654183;
234 | s8 -= s17 * 997805;
235 | s9 += s17 * 136657;
236 | s10 -= s17 * 683901;
237 | s17 = 0;
238 |
239 | s4 += s16 * 666643;
240 | s5 += s16 * 470296;
241 | s6 += s16 * 654183;
242 | s7 -= s16 * 997805;
243 | s8 += s16 * 136657;
244 | s9 -= s16 * 683901;
245 | s16 = 0;
246 |
247 | s3 += s15 * 666643;
248 | s4 += s15 * 470296;
249 | s5 += s15 * 654183;
250 | s6 -= s15 * 997805;
251 | s7 += s15 * 136657;
252 | s8 -= s15 * 683901;
253 | s15 = 0;
254 |
255 | s2 += s14 * 666643;
256 | s3 += s14 * 470296;
257 | s4 += s14 * 654183;
258 | s5 -= s14 * 997805;
259 | s6 += s14 * 136657;
260 | s7 -= s14 * 683901;
261 | s14 = 0;
262 |
263 | s1 += s13 * 666643;
264 | s2 += s13 * 470296;
265 | s3 += s13 * 654183;
266 | s4 -= s13 * 997805;
267 | s5 += s13 * 136657;
268 | s6 -= s13 * 683901;
269 | s13 = 0;
270 |
271 | s0 += s12 * 666643;
272 | s1 += s12 * 470296;
273 | s2 += s12 * 654183;
274 | s3 -= s12 * 997805;
275 | s4 += s12 * 136657;
276 | s5 -= s12 * 683901;
277 | s12 = 0;
278 |
279 | carry0 = (s0 + (1<<20)) >> 21; s1 += carry0; s0 -= carry0 << 21;
280 | carry2 = (s2 + (1<<20)) >> 21; s3 += carry2; s2 -= carry2 << 21;
281 | carry4 = (s4 + (1<<20)) >> 21; s5 += carry4; s4 -= carry4 << 21;
282 | carry6 = (s6 + (1<<20)) >> 21; s7 += carry6; s6 -= carry6 << 21;
283 | carry8 = (s8 + (1<<20)) >> 21; s9 += carry8; s8 -= carry8 << 21;
284 | carry10 = (s10 + (1<<20)) >> 21; s11 += carry10; s10 -= carry10 << 21;
285 |
286 | carry1 = (s1 + (1<<20)) >> 21; s2 += carry1; s1 -= carry1 << 21;
287 | carry3 = (s3 + (1<<20)) >> 21; s4 += carry3; s3 -= carry3 << 21;
288 | carry5 = (s5 + (1<<20)) >> 21; s6 += carry5; s5 -= carry5 << 21;
289 | carry7 = (s7 + (1<<20)) >> 21; s8 += carry7; s7 -= carry7 << 21;
290 | carry9 = (s9 + (1<<20)) >> 21; s10 += carry9; s9 -= carry9 << 21;
291 | carry11 = (s11 + (1<<20)) >> 21; s12 += carry11; s11 -= carry11 << 21;
292 |
293 | s0 += s12 * 666643;
294 | s1 += s12 * 470296;
295 | s2 += s12 * 654183;
296 | s3 -= s12 * 997805;
297 | s4 += s12 * 136657;
298 | s5 -= s12 * 683901;
299 | s12 = 0;
300 |
301 | carry0 = s0 >> 21; s1 += carry0; s0 -= carry0 << 21;
302 | carry1 = s1 >> 21; s2 += carry1; s1 -= carry1 << 21;
303 | carry2 = s2 >> 21; s3 += carry2; s2 -= carry2 << 21;
304 | carry3 = s3 >> 21; s4 += carry3; s3 -= carry3 << 21;
305 | carry4 = s4 >> 21; s5 += carry4; s4 -= carry4 << 21;
306 | carry5 = s5 >> 21; s6 += carry5; s5 -= carry5 << 21;
307 | carry6 = s6 >> 21; s7 += carry6; s6 -= carry6 << 21;
308 | carry7 = s7 >> 21; s8 += carry7; s7 -= carry7 << 21;
309 | carry8 = s8 >> 21; s9 += carry8; s8 -= carry8 << 21;
310 | carry9 = s9 >> 21; s10 += carry9; s9 -= carry9 << 21;
311 | carry10 = s10 >> 21; s11 += carry10; s10 -= carry10 << 21;
312 | carry11 = s11 >> 21; s12 += carry11; s11 -= carry11 << 21;
313 |
314 | s0 += s12 * 666643;
315 | s1 += s12 * 470296;
316 | s2 += s12 * 654183;
317 | s3 -= s12 * 997805;
318 | s4 += s12 * 136657;
319 | s5 -= s12 * 683901;
320 | s12 = 0;
321 |
322 | carry0 = s0 >> 21; s1 += carry0; s0 -= carry0 << 21;
323 | carry1 = s1 >> 21; s2 += carry1; s1 -= carry1 << 21;
324 | carry2 = s2 >> 21; s3 += carry2; s2 -= carry2 << 21;
325 | carry3 = s3 >> 21; s4 += carry3; s3 -= carry3 << 21;
326 | carry4 = s4 >> 21; s5 += carry4; s4 -= carry4 << 21;
327 | carry5 = s5 >> 21; s6 += carry5; s5 -= carry5 << 21;
328 | carry6 = s6 >> 21; s7 += carry6; s6 -= carry6 << 21;
329 | carry7 = s7 >> 21; s8 += carry7; s7 -= carry7 << 21;
330 | carry8 = s8 >> 21; s9 += carry8; s8 -= carry8 << 21;
331 | carry9 = s9 >> 21; s10 += carry9; s9 -= carry9 << 21;
332 | carry10 = s10 >> 21; s11 += carry10; s10 -= carry10 << 21;
333 |
334 | s[0] = s0 >> 0;
335 | s[1] = s0 >> 8;
336 | s[2] = (s0 >> 16) | (s1 << 5);
337 | s[3] = s1 >> 3;
338 | s[4] = s1 >> 11;
339 | s[5] = (s1 >> 19) | (s2 << 2);
340 | s[6] = s2 >> 6;
341 | s[7] = (s2 >> 14) | (s3 << 7);
342 | s[8] = s3 >> 1;
343 | s[9] = s3 >> 9;
344 | s[10] = (s3 >> 17) | (s4 << 4);
345 | s[11] = s4 >> 4;
346 | s[12] = s4 >> 12;
347 | s[13] = (s4 >> 20) | (s5 << 1);
348 | s[14] = s5 >> 7;
349 | s[15] = (s5 >> 15) | (s6 << 6);
350 | s[16] = s6 >> 2;
351 | s[17] = s6 >> 10;
352 | s[18] = (s6 >> 18) | (s7 << 3);
353 | s[19] = s7 >> 5;
354 | s[20] = s7 >> 13;
355 | s[21] = s8 >> 0;
356 | s[22] = s8 >> 8;
357 | s[23] = (s8 >> 16) | (s9 << 5);
358 | s[24] = s9 >> 3;
359 | s[25] = s9 >> 11;
360 | s[26] = (s9 >> 19) | (s10 << 2);
361 | s[27] = s10 >> 6;
362 | s[28] = (s10 >> 14) | (s11 << 7);
363 | s[29] = s11 >> 1;
364 | s[30] = s11 >> 9;
365 | s[31] = s11 >> 17;
366 | }
367 |
--------------------------------------------------------------------------------
/ext/ed25519_ref10/sc_reduce.c:
--------------------------------------------------------------------------------
1 | #include "sc.h"
2 |
3 | static uint64_t load_3(const unsigned char *in)
4 | {
5 | uint64_t result;
6 | result = (uint64_t) in[0];
7 | result |= ((uint64_t) in[1]) << 8;
8 | result |= ((uint64_t) in[2]) << 16;
9 | return result;
10 | }
11 |
12 | static uint64_t load_4(const unsigned char *in)
13 | {
14 | uint64_t result;
15 | result = (uint64_t) in[0];
16 | result |= ((uint64_t) in[1]) << 8;
17 | result |= ((uint64_t) in[2]) << 16;
18 | result |= ((uint64_t) in[3]) << 24;
19 | return result;
20 | }
21 |
22 | /*
23 | Input:
24 | s[0]+256*s[1]+...+256^63*s[63] = s
25 |
26 | Output:
27 | s[0]+256*s[1]+...+256^31*s[31] = s mod l
28 | where l = 2^252 + 27742317777372353535851937790883648493.
29 | Overwrites s in place.
30 | */
31 |
32 | void sc_reduce(uint8_t *s)
33 | {
34 | int64_t s0 = 2097151 & load_3(s);
35 | int64_t s1 = 2097151 & (load_4(s + 2) >> 5);
36 | int64_t s2 = 2097151 & (load_3(s + 5) >> 2);
37 | int64_t s3 = 2097151 & (load_4(s + 7) >> 7);
38 | int64_t s4 = 2097151 & (load_4(s + 10) >> 4);
39 | int64_t s5 = 2097151 & (load_3(s + 13) >> 1);
40 | int64_t s6 = 2097151 & (load_4(s + 15) >> 6);
41 | int64_t s7 = 2097151 & (load_3(s + 18) >> 3);
42 | int64_t s8 = 2097151 & load_3(s + 21);
43 | int64_t s9 = 2097151 & (load_4(s + 23) >> 5);
44 | int64_t s10 = 2097151 & (load_3(s + 26) >> 2);
45 | int64_t s11 = 2097151 & (load_4(s + 28) >> 7);
46 | int64_t s12 = 2097151 & (load_4(s + 31) >> 4);
47 | int64_t s13 = 2097151 & (load_3(s + 34) >> 1);
48 | int64_t s14 = 2097151 & (load_4(s + 36) >> 6);
49 | int64_t s15 = 2097151 & (load_3(s + 39) >> 3);
50 | int64_t s16 = 2097151 & load_3(s + 42);
51 | int64_t s17 = 2097151 & (load_4(s + 44) >> 5);
52 | int64_t s18 = 2097151 & (load_3(s + 47) >> 2);
53 | int64_t s19 = 2097151 & (load_4(s + 49) >> 7);
54 | int64_t s20 = 2097151 & (load_4(s + 52) >> 4);
55 | int64_t s21 = 2097151 & (load_3(s + 55) >> 1);
56 | int64_t s22 = 2097151 & (load_4(s + 57) >> 6);
57 | int64_t s23 = (load_4(s + 60) >> 3);
58 | int64_t carry0;
59 | int64_t carry1;
60 | int64_t carry2;
61 | int64_t carry3;
62 | int64_t carry4;
63 | int64_t carry5;
64 | int64_t carry6;
65 | int64_t carry7;
66 | int64_t carry8;
67 | int64_t carry9;
68 | int64_t carry10;
69 | int64_t carry11;
70 | int64_t carry12;
71 | int64_t carry13;
72 | int64_t carry14;
73 | int64_t carry15;
74 | int64_t carry16;
75 |
76 | s11 += s23 * 666643;
77 | s12 += s23 * 470296;
78 | s13 += s23 * 654183;
79 | s14 -= s23 * 997805;
80 | s15 += s23 * 136657;
81 | s16 -= s23 * 683901;
82 | s23 = 0;
83 |
84 | s10 += s22 * 666643;
85 | s11 += s22 * 470296;
86 | s12 += s22 * 654183;
87 | s13 -= s22 * 997805;
88 | s14 += s22 * 136657;
89 | s15 -= s22 * 683901;
90 | s22 = 0;
91 |
92 | s9 += s21 * 666643;
93 | s10 += s21 * 470296;
94 | s11 += s21 * 654183;
95 | s12 -= s21 * 997805;
96 | s13 += s21 * 136657;
97 | s14 -= s21 * 683901;
98 | s21 = 0;
99 |
100 | s8 += s20 * 666643;
101 | s9 += s20 * 470296;
102 | s10 += s20 * 654183;
103 | s11 -= s20 * 997805;
104 | s12 += s20 * 136657;
105 | s13 -= s20 * 683901;
106 | s20 = 0;
107 |
108 | s7 += s19 * 666643;
109 | s8 += s19 * 470296;
110 | s9 += s19 * 654183;
111 | s10 -= s19 * 997805;
112 | s11 += s19 * 136657;
113 | s12 -= s19 * 683901;
114 | s19 = 0;
115 |
116 | s6 += s18 * 666643;
117 | s7 += s18 * 470296;
118 | s8 += s18 * 654183;
119 | s9 -= s18 * 997805;
120 | s10 += s18 * 136657;
121 | s11 -= s18 * 683901;
122 | s18 = 0;
123 |
124 | carry6 = (s6 + (1<<20)) >> 21; s7 += carry6; s6 -= carry6 << 21;
125 | carry8 = (s8 + (1<<20)) >> 21; s9 += carry8; s8 -= carry8 << 21;
126 | carry10 = (s10 + (1<<20)) >> 21; s11 += carry10; s10 -= carry10 << 21;
127 | carry12 = (s12 + (1<<20)) >> 21; s13 += carry12; s12 -= carry12 << 21;
128 | carry14 = (s14 + (1<<20)) >> 21; s15 += carry14; s14 -= carry14 << 21;
129 | carry16 = (s16 + (1<<20)) >> 21; s17 += carry16; s16 -= carry16 << 21;
130 |
131 | carry7 = (s7 + (1<<20)) >> 21; s8 += carry7; s7 -= carry7 << 21;
132 | carry9 = (s9 + (1<<20)) >> 21; s10 += carry9; s9 -= carry9 << 21;
133 | carry11 = (s11 + (1<<20)) >> 21; s12 += carry11; s11 -= carry11 << 21;
134 | carry13 = (s13 + (1<<20)) >> 21; s14 += carry13; s13 -= carry13 << 21;
135 | carry15 = (s15 + (1<<20)) >> 21; s16 += carry15; s15 -= carry15 << 21;
136 |
137 | s5 += s17 * 666643;
138 | s6 += s17 * 470296;
139 | s7 += s17 * 654183;
140 | s8 -= s17 * 997805;
141 | s9 += s17 * 136657;
142 | s10 -= s17 * 683901;
143 | s17 = 0;
144 |
145 | s4 += s16 * 666643;
146 | s5 += s16 * 470296;
147 | s6 += s16 * 654183;
148 | s7 -= s16 * 997805;
149 | s8 += s16 * 136657;
150 | s9 -= s16 * 683901;
151 | s16 = 0;
152 |
153 | s3 += s15 * 666643;
154 | s4 += s15 * 470296;
155 | s5 += s15 * 654183;
156 | s6 -= s15 * 997805;
157 | s7 += s15 * 136657;
158 | s8 -= s15 * 683901;
159 | s15 = 0;
160 |
161 | s2 += s14 * 666643;
162 | s3 += s14 * 470296;
163 | s4 += s14 * 654183;
164 | s5 -= s14 * 997805;
165 | s6 += s14 * 136657;
166 | s7 -= s14 * 683901;
167 | s14 = 0;
168 |
169 | s1 += s13 * 666643;
170 | s2 += s13 * 470296;
171 | s3 += s13 * 654183;
172 | s4 -= s13 * 997805;
173 | s5 += s13 * 136657;
174 | s6 -= s13 * 683901;
175 | s13 = 0;
176 |
177 | s0 += s12 * 666643;
178 | s1 += s12 * 470296;
179 | s2 += s12 * 654183;
180 | s3 -= s12 * 997805;
181 | s4 += s12 * 136657;
182 | s5 -= s12 * 683901;
183 | s12 = 0;
184 |
185 | carry0 = (s0 + (1<<20)) >> 21; s1 += carry0; s0 -= carry0 << 21;
186 | carry2 = (s2 + (1<<20)) >> 21; s3 += carry2; s2 -= carry2 << 21;
187 | carry4 = (s4 + (1<<20)) >> 21; s5 += carry4; s4 -= carry4 << 21;
188 | carry6 = (s6 + (1<<20)) >> 21; s7 += carry6; s6 -= carry6 << 21;
189 | carry8 = (s8 + (1<<20)) >> 21; s9 += carry8; s8 -= carry8 << 21;
190 | carry10 = (s10 + (1<<20)) >> 21; s11 += carry10; s10 -= carry10 << 21;
191 |
192 | carry1 = (s1 + (1<<20)) >> 21; s2 += carry1; s1 -= carry1 << 21;
193 | carry3 = (s3 + (1<<20)) >> 21; s4 += carry3; s3 -= carry3 << 21;
194 | carry5 = (s5 + (1<<20)) >> 21; s6 += carry5; s5 -= carry5 << 21;
195 | carry7 = (s7 + (1<<20)) >> 21; s8 += carry7; s7 -= carry7 << 21;
196 | carry9 = (s9 + (1<<20)) >> 21; s10 += carry9; s9 -= carry9 << 21;
197 | carry11 = (s11 + (1<<20)) >> 21; s12 += carry11; s11 -= carry11 << 21;
198 |
199 | s0 += s12 * 666643;
200 | s1 += s12 * 470296;
201 | s2 += s12 * 654183;
202 | s3 -= s12 * 997805;
203 | s4 += s12 * 136657;
204 | s5 -= s12 * 683901;
205 | s12 = 0;
206 |
207 | carry0 = s0 >> 21; s1 += carry0; s0 -= carry0 << 21;
208 | carry1 = s1 >> 21; s2 += carry1; s1 -= carry1 << 21;
209 | carry2 = s2 >> 21; s3 += carry2; s2 -= carry2 << 21;
210 | carry3 = s3 >> 21; s4 += carry3; s3 -= carry3 << 21;
211 | carry4 = s4 >> 21; s5 += carry4; s4 -= carry4 << 21;
212 | carry5 = s5 >> 21; s6 += carry5; s5 -= carry5 << 21;
213 | carry6 = s6 >> 21; s7 += carry6; s6 -= carry6 << 21;
214 | carry7 = s7 >> 21; s8 += carry7; s7 -= carry7 << 21;
215 | carry8 = s8 >> 21; s9 += carry8; s8 -= carry8 << 21;
216 | carry9 = s9 >> 21; s10 += carry9; s9 -= carry9 << 21;
217 | carry10 = s10 >> 21; s11 += carry10; s10 -= carry10 << 21;
218 | carry11 = s11 >> 21; s12 += carry11; s11 -= carry11 << 21;
219 |
220 | s0 += s12 * 666643;
221 | s1 += s12 * 470296;
222 | s2 += s12 * 654183;
223 | s3 -= s12 * 997805;
224 | s4 += s12 * 136657;
225 | s5 -= s12 * 683901;
226 | s12 = 0;
227 |
228 | carry0 = s0 >> 21; s1 += carry0; s0 -= carry0 << 21;
229 | carry1 = s1 >> 21; s2 += carry1; s1 -= carry1 << 21;
230 | carry2 = s2 >> 21; s3 += carry2; s2 -= carry2 << 21;
231 | carry3 = s3 >> 21; s4 += carry3; s3 -= carry3 << 21;
232 | carry4 = s4 >> 21; s5 += carry4; s4 -= carry4 << 21;
233 | carry5 = s5 >> 21; s6 += carry5; s5 -= carry5 << 21;
234 | carry6 = s6 >> 21; s7 += carry6; s6 -= carry6 << 21;
235 | carry7 = s7 >> 21; s8 += carry7; s7 -= carry7 << 21;
236 | carry8 = s8 >> 21; s9 += carry8; s8 -= carry8 << 21;
237 | carry9 = s9 >> 21; s10 += carry9; s9 -= carry9 << 21;
238 | carry10 = s10 >> 21; s11 += carry10; s10 -= carry10 << 21;
239 |
240 | s[0] = s0 >> 0;
241 | s[1] = s0 >> 8;
242 | s[2] = (s0 >> 16) | (s1 << 5);
243 | s[3] = s1 >> 3;
244 | s[4] = s1 >> 11;
245 | s[5] = (s1 >> 19) | (s2 << 2);
246 | s[6] = s2 >> 6;
247 | s[7] = (s2 >> 14) | (s3 << 7);
248 | s[8] = s3 >> 1;
249 | s[9] = s3 >> 9;
250 | s[10] = (s3 >> 17) | (s4 << 4);
251 | s[11] = s4 >> 4;
252 | s[12] = s4 >> 12;
253 | s[13] = (s4 >> 20) | (s5 << 1);
254 | s[14] = s5 >> 7;
255 | s[15] = (s5 >> 15) | (s6 << 6);
256 | s[16] = s6 >> 2;
257 | s[17] = s6 >> 10;
258 | s[18] = (s6 >> 18) | (s7 << 3);
259 | s[19] = s7 >> 5;
260 | s[20] = s7 >> 13;
261 | s[21] = s8 >> 0;
262 | s[22] = s8 >> 8;
263 | s[23] = (s8 >> 16) | (s9 << 5);
264 | s[24] = s9 >> 3;
265 | s[25] = s9 >> 11;
266 | s[26] = (s9 >> 19) | (s10 << 2);
267 | s[27] = s10 >> 6;
268 | s[28] = (s10 >> 14) | (s11 << 7);
269 | s[29] = s11 >> 1;
270 | s[30] = s11 >> 9;
271 | s[31] = s11 >> 17;
272 | }
273 |
--------------------------------------------------------------------------------
/ext/ed25519_ref10/sha512.c:
--------------------------------------------------------------------------------
1 | /*
2 | 20080913
3 | D. J. Bernstein
4 | Public domain.
5 | */
6 |
7 | #include "sha512.h"
8 |
9 | static void crypto_hashblocks_sha512(uint8_t *statebytes,const uint8_t *in,uint64_t inlen);
10 |
11 | #define blocks crypto_hashblocks_sha512
12 |
13 | static const uint8_t iv[64] = {
14 | 0x6a,0x09,0xe6,0x67,0xf3,0xbc,0xc9,0x08,
15 | 0xbb,0x67,0xae,0x85,0x84,0xca,0xa7,0x3b,
16 | 0x3c,0x6e,0xf3,0x72,0xfe,0x94,0xf8,0x2b,
17 | 0xa5,0x4f,0xf5,0x3a,0x5f,0x1d,0x36,0xf1,
18 | 0x51,0x0e,0x52,0x7f,0xad,0xe6,0x82,0xd1,
19 | 0x9b,0x05,0x68,0x8c,0x2b,0x3e,0x6c,0x1f,
20 | 0x1f,0x83,0xd9,0xab,0xfb,0x41,0xbd,0x6b,
21 | 0x5b,0xe0,0xcd,0x19,0x13,0x7e,0x21,0x79
22 | };
23 |
24 | int crypto_hash_sha512(uint8_t *out,const uint8_t *in,uint64_t inlen)
25 | {
26 | uint8_t h[64];
27 | uint8_t padded[256];
28 | uint64_t i;
29 | uint64_t bytes = inlen;
30 |
31 | for (i = 0;i < 64;++i) h[i] = iv[i];
32 |
33 | blocks(h,in,inlen);
34 | in += inlen;
35 | inlen &= 127;
36 | in -= inlen;
37 |
38 | for (i = 0;i < inlen;++i) padded[i] = in[i];
39 | padded[inlen] = 0x80;
40 |
41 | if (inlen < 112) {
42 | for (i = inlen + 1;i < 119;++i) padded[i] = 0;
43 | padded[119] = bytes >> 61;
44 | padded[120] = bytes >> 53;
45 | padded[121] = bytes >> 45;
46 | padded[122] = bytes >> 37;
47 | padded[123] = bytes >> 29;
48 | padded[124] = bytes >> 21;
49 | padded[125] = bytes >> 13;
50 | padded[126] = bytes >> 5;
51 | padded[127] = bytes << 3;
52 | blocks(h,padded,128);
53 | } else {
54 | for (i = inlen + 1;i < 247;++i) padded[i] = 0;
55 | padded[247] = bytes >> 61;
56 | padded[248] = bytes >> 53;
57 | padded[249] = bytes >> 45;
58 | padded[250] = bytes >> 37;
59 | padded[251] = bytes >> 29;
60 | padded[252] = bytes >> 21;
61 | padded[253] = bytes >> 13;
62 | padded[254] = bytes >> 5;
63 | padded[255] = bytes << 3;
64 | blocks(h,padded,256);
65 | }
66 |
67 | for (i = 0;i < 64;++i) out[i] = h[i];
68 |
69 | return 0;
70 | }
71 |
72 | static uint64_t load_bigendian(const unsigned char *x)
73 | {
74 | return
75 | (uint64_t) (x[7]) \
76 | | (((uint64_t) (x[6])) << 8) \
77 | | (((uint64_t) (x[5])) << 16) \
78 | | (((uint64_t) (x[4])) << 24) \
79 | | (((uint64_t) (x[3])) << 32) \
80 | | (((uint64_t) (x[2])) << 40) \
81 | | (((uint64_t) (x[1])) << 48) \
82 | | (((uint64_t) (x[0])) << 56)
83 | ;
84 | }
85 |
86 | static void store_bigendian(unsigned char *x,uint64_t u)
87 | {
88 | x[7] = u; u >>= 8;
89 | x[6] = u; u >>= 8;
90 | x[5] = u; u >>= 8;
91 | x[4] = u; u >>= 8;
92 | x[3] = u; u >>= 8;
93 | x[2] = u; u >>= 8;
94 | x[1] = u; u >>= 8;
95 | x[0] = u;
96 | }
97 |
98 | #define SHR(x,c) ((x) >> (c))
99 | #define ROTR(x,c) (((x) >> (c)) | ((x) << (64 - (c))))
100 |
101 | #define Ch(x,y,z) ((x & y) ^ (~x & z))
102 | #define Maj(x,y,z) ((x & y) ^ (x & z) ^ (y & z))
103 | #define Sigma0(x) (ROTR(x,28) ^ ROTR(x,34) ^ ROTR(x,39))
104 | #define Sigma1(x) (ROTR(x,14) ^ ROTR(x,18) ^ ROTR(x,41))
105 | #define sigma0(x) (ROTR(x, 1) ^ ROTR(x, 8) ^ SHR(x,7))
106 | #define sigma1(x) (ROTR(x,19) ^ ROTR(x,61) ^ SHR(x,6))
107 |
108 | #define M(w0,w14,w9,w1) w0 = sigma1(w14) + w9 + sigma0(w1) + w0;
109 |
110 | #define EXPAND \
111 | M(w0 ,w14,w9 ,w1 ) \
112 | M(w1 ,w15,w10,w2 ) \
113 | M(w2 ,w0 ,w11,w3 ) \
114 | M(w3 ,w1 ,w12,w4 ) \
115 | M(w4 ,w2 ,w13,w5 ) \
116 | M(w5 ,w3 ,w14,w6 ) \
117 | M(w6 ,w4 ,w15,w7 ) \
118 | M(w7 ,w5 ,w0 ,w8 ) \
119 | M(w8 ,w6 ,w1 ,w9 ) \
120 | M(w9 ,w7 ,w2 ,w10) \
121 | M(w10,w8 ,w3 ,w11) \
122 | M(w11,w9 ,w4 ,w12) \
123 | M(w12,w10,w5 ,w13) \
124 | M(w13,w11,w6 ,w14) \
125 | M(w14,w12,w7 ,w15) \
126 | M(w15,w13,w8 ,w0 )
127 |
128 | #define F(w,k) \
129 | T1 = h + Sigma1(e) + Ch(e,f,g) + k + w; \
130 | T2 = Sigma0(a) + Maj(a,b,c); \
131 | h = g; \
132 | g = f; \
133 | f = e; \
134 | e = d + T1; \
135 | d = c; \
136 | c = b; \
137 | b = a; \
138 | a = T1 + T2;
139 |
140 | static void crypto_hashblocks_sha512(uint8_t *statebytes,const uint8_t *in,uint64_t inlen)
141 | {
142 | uint64_t state[8];
143 | uint64_t a;
144 | uint64_t b;
145 | uint64_t c;
146 | uint64_t d;
147 | uint64_t e;
148 | uint64_t f;
149 | uint64_t g;
150 | uint64_t h;
151 | uint64_t T1;
152 | uint64_t T2;
153 |
154 | a = load_bigendian(statebytes + 0); state[0] = a;
155 | b = load_bigendian(statebytes + 8); state[1] = b;
156 | c = load_bigendian(statebytes + 16); state[2] = c;
157 | d = load_bigendian(statebytes + 24); state[3] = d;
158 | e = load_bigendian(statebytes + 32); state[4] = e;
159 | f = load_bigendian(statebytes + 40); state[5] = f;
160 | g = load_bigendian(statebytes + 48); state[6] = g;
161 | h = load_bigendian(statebytes + 56); state[7] = h;
162 |
163 | while (inlen >= 128) {
164 | uint64_t w0 = load_bigendian(in + 0);
165 | uint64_t w1 = load_bigendian(in + 8);
166 | uint64_t w2 = load_bigendian(in + 16);
167 | uint64_t w3 = load_bigendian(in + 24);
168 | uint64_t w4 = load_bigendian(in + 32);
169 | uint64_t w5 = load_bigendian(in + 40);
170 | uint64_t w6 = load_bigendian(in + 48);
171 | uint64_t w7 = load_bigendian(in + 56);
172 | uint64_t w8 = load_bigendian(in + 64);
173 | uint64_t w9 = load_bigendian(in + 72);
174 | uint64_t w10 = load_bigendian(in + 80);
175 | uint64_t w11 = load_bigendian(in + 88);
176 | uint64_t w12 = load_bigendian(in + 96);
177 | uint64_t w13 = load_bigendian(in + 104);
178 | uint64_t w14 = load_bigendian(in + 112);
179 | uint64_t w15 = load_bigendian(in + 120);
180 |
181 | F(w0 ,0x428a2f98d728ae22ULL)
182 | F(w1 ,0x7137449123ef65cdULL)
183 | F(w2 ,0xb5c0fbcfec4d3b2fULL)
184 | F(w3 ,0xe9b5dba58189dbbcULL)
185 | F(w4 ,0x3956c25bf348b538ULL)
186 | F(w5 ,0x59f111f1b605d019ULL)
187 | F(w6 ,0x923f82a4af194f9bULL)
188 | F(w7 ,0xab1c5ed5da6d8118ULL)
189 | F(w8 ,0xd807aa98a3030242ULL)
190 | F(w9 ,0x12835b0145706fbeULL)
191 | F(w10,0x243185be4ee4b28cULL)
192 | F(w11,0x550c7dc3d5ffb4e2ULL)
193 | F(w12,0x72be5d74f27b896fULL)
194 | F(w13,0x80deb1fe3b1696b1ULL)
195 | F(w14,0x9bdc06a725c71235ULL)
196 | F(w15,0xc19bf174cf692694ULL)
197 |
198 | EXPAND
199 |
200 | F(w0 ,0xe49b69c19ef14ad2ULL)
201 | F(w1 ,0xefbe4786384f25e3ULL)
202 | F(w2 ,0x0fc19dc68b8cd5b5ULL)
203 | F(w3 ,0x240ca1cc77ac9c65ULL)
204 | F(w4 ,0x2de92c6f592b0275ULL)
205 | F(w5 ,0x4a7484aa6ea6e483ULL)
206 | F(w6 ,0x5cb0a9dcbd41fbd4ULL)
207 | F(w7 ,0x76f988da831153b5ULL)
208 | F(w8 ,0x983e5152ee66dfabULL)
209 | F(w9 ,0xa831c66d2db43210ULL)
210 | F(w10,0xb00327c898fb213fULL)
211 | F(w11,0xbf597fc7beef0ee4ULL)
212 | F(w12,0xc6e00bf33da88fc2ULL)
213 | F(w13,0xd5a79147930aa725ULL)
214 | F(w14,0x06ca6351e003826fULL)
215 | F(w15,0x142929670a0e6e70ULL)
216 |
217 | EXPAND
218 |
219 | F(w0 ,0x27b70a8546d22ffcULL)
220 | F(w1 ,0x2e1b21385c26c926ULL)
221 | F(w2 ,0x4d2c6dfc5ac42aedULL)
222 | F(w3 ,0x53380d139d95b3dfULL)
223 | F(w4 ,0x650a73548baf63deULL)
224 | F(w5 ,0x766a0abb3c77b2a8ULL)
225 | F(w6 ,0x81c2c92e47edaee6ULL)
226 | F(w7 ,0x92722c851482353bULL)
227 | F(w8 ,0xa2bfe8a14cf10364ULL)
228 | F(w9 ,0xa81a664bbc423001ULL)
229 | F(w10,0xc24b8b70d0f89791ULL)
230 | F(w11,0xc76c51a30654be30ULL)
231 | F(w12,0xd192e819d6ef5218ULL)
232 | F(w13,0xd69906245565a910ULL)
233 | F(w14,0xf40e35855771202aULL)
234 | F(w15,0x106aa07032bbd1b8ULL)
235 |
236 | EXPAND
237 |
238 | F(w0 ,0x19a4c116b8d2d0c8ULL)
239 | F(w1 ,0x1e376c085141ab53ULL)
240 | F(w2 ,0x2748774cdf8eeb99ULL)
241 | F(w3 ,0x34b0bcb5e19b48a8ULL)
242 | F(w4 ,0x391c0cb3c5c95a63ULL)
243 | F(w5 ,0x4ed8aa4ae3418acbULL)
244 | F(w6 ,0x5b9cca4f7763e373ULL)
245 | F(w7 ,0x682e6ff3d6b2b8a3ULL)
246 | F(w8 ,0x748f82ee5defb2fcULL)
247 | F(w9 ,0x78a5636f43172f60ULL)
248 | F(w10,0x84c87814a1f0ab72ULL)
249 | F(w11,0x8cc702081a6439ecULL)
250 | F(w12,0x90befffa23631e28ULL)
251 | F(w13,0xa4506cebde82bde9ULL)
252 | F(w14,0xbef9a3f7b2c67915ULL)
253 | F(w15,0xc67178f2e372532bULL)
254 |
255 | EXPAND
256 |
257 | F(w0 ,0xca273eceea26619cULL)
258 | F(w1 ,0xd186b8c721c0c207ULL)
259 | F(w2 ,0xeada7dd6cde0eb1eULL)
260 | F(w3 ,0xf57d4f7fee6ed178ULL)
261 | F(w4 ,0x06f067aa72176fbaULL)
262 | F(w5 ,0x0a637dc5a2c898a6ULL)
263 | F(w6 ,0x113f9804bef90daeULL)
264 | F(w7 ,0x1b710b35131c471bULL)
265 | F(w8 ,0x28db77f523047d84ULL)
266 | F(w9 ,0x32caab7b40c72493ULL)
267 | F(w10,0x3c9ebe0a15c9bebcULL)
268 | F(w11,0x431d67c49c100d4cULL)
269 | F(w12,0x4cc5d4becb3e42b6ULL)
270 | F(w13,0x597f299cfc657e2aULL)
271 | F(w14,0x5fcb6fab3ad6faecULL)
272 | F(w15,0x6c44198c4a475817ULL)
273 |
274 | a += state[0];
275 | b += state[1];
276 | c += state[2];
277 | d += state[3];
278 | e += state[4];
279 | f += state[5];
280 | g += state[6];
281 | h += state[7];
282 |
283 | state[0] = a;
284 | state[1] = b;
285 | state[2] = c;
286 | state[3] = d;
287 | state[4] = e;
288 | state[5] = f;
289 | state[6] = g;
290 | state[7] = h;
291 |
292 | in += 128;
293 | inlen -= 128;
294 | }
295 |
296 | store_bigendian(statebytes + 0,state[0]);
297 | store_bigendian(statebytes + 8,state[1]);
298 | store_bigendian(statebytes + 16,state[2]);
299 | store_bigendian(statebytes + 24,state[3]);
300 | store_bigendian(statebytes + 32,state[4]);
301 | store_bigendian(statebytes + 40,state[5]);
302 | store_bigendian(statebytes + 48,state[6]);
303 | store_bigendian(statebytes + 56,state[7]);
304 | }
305 |
--------------------------------------------------------------------------------
/ext/ed25519_ref10/sha512.h:
--------------------------------------------------------------------------------
1 | #ifndef SHA512_H
2 | #define SHA512_H
3 |
4 | #include
5 |
6 | int crypto_hash_sha512(uint8_t *out,const uint8_t *in,uint64_t inlen);
7 |
8 | #endif /* SHA512_H */
9 |
--------------------------------------------------------------------------------
/ext/ed25519_ref10/sign.c:
--------------------------------------------------------------------------------
1 | #include
2 | #include "ed25519_ref10.h"
3 | #include "sha512.h"
4 | #include "ge.h"
5 | #include "sc.h"
6 |
7 | int crypto_sign_ed25519_ref10(
8 | uint8_t *sm, uint64_t *smlen,
9 | const uint8_t *m, uint64_t mlen,
10 | const uint8_t *sk
11 | )
12 | {
13 | unsigned char pk[32];
14 | unsigned char az[64];
15 | unsigned char nonce[64];
16 | unsigned char hram[64];
17 | ge_p3 R;
18 |
19 | memmove(pk,sk + 32,32);
20 |
21 | crypto_hash_sha512(az,sk,32);
22 | az[0] &= 248;
23 | az[31] &= 63;
24 | az[31] |= 64;
25 |
26 | *smlen = mlen + 64;
27 | memmove(sm + 64,m,mlen);
28 | memmove(sm + 32,az + 32,32);
29 | crypto_hash_sha512(nonce,sm + 32,mlen + 32);
30 | memmove(sm + 32,pk,32);
31 |
32 | sc_reduce(nonce);
33 | ge_scalarmult_base(&R,nonce);
34 | ge_p3_tobytes(sm,&R);
35 |
36 | crypto_hash_sha512(hram,sm,mlen + 64);
37 | sc_reduce(hram);
38 | sc_muladd(sm + 32,hram,az,nonce);
39 |
40 | return 0;
41 | }
42 |
--------------------------------------------------------------------------------
/ext/ed25519_ref10/sqrtm1.h:
--------------------------------------------------------------------------------
1 | -32595792,-7943725,9377950,3500415,12389472,-272473,-25146209,-2005654,326686,11406482
2 |
--------------------------------------------------------------------------------
/ext/ed25519_ref10/verify.c:
--------------------------------------------------------------------------------
1 | #include "ed25519_ref10.h"
2 |
3 | int crypto_verify_32(const uint8_t *x,const uint8_t *y)
4 | {
5 | unsigned int differentbits = 0;
6 | #define F(i) differentbits |= x[i] ^ y[i];
7 | F(0)
8 | F(1)
9 | F(2)
10 | F(3)
11 | F(4)
12 | F(5)
13 | F(6)
14 | F(7)
15 | F(8)
16 | F(9)
17 | F(10)
18 | F(11)
19 | F(12)
20 | F(13)
21 | F(14)
22 | F(15)
23 | F(16)
24 | F(17)
25 | F(18)
26 | F(19)
27 | F(20)
28 | F(21)
29 | F(22)
30 | F(23)
31 | F(24)
32 | F(25)
33 | F(26)
34 | F(27)
35 | F(28)
36 | F(29)
37 | F(30)
38 | F(31)
39 | return (1 & ((differentbits - 1) >> 8)) - 1;
40 | }
41 |
--------------------------------------------------------------------------------
/lib/ed25519.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 |
3 | require "ed25519/version"
4 | require "ed25519/signing_key"
5 | require "ed25519/verify_key"
6 |
7 | # The Ed25519 digital signatre algorithm
8 | # rubocop:disable Layout/LineLength
9 | module Ed25519
10 | module_function
11 |
12 | # Size of an Ed25519 key (public or private) in bytes
13 | KEY_SIZE = 32
14 |
15 | # Size of an Ed25519 signature in bytes
16 | SIGNATURE_SIZE = 64
17 |
18 | # Raised when a signature fails to verify
19 | VerifyError = Class.new(StandardError)
20 |
21 | # Raised when the built-in self-test fails
22 | SelfTestFailure = Class.new(StandardError)
23 |
24 | class << self
25 | # Obtain the backend provider module used to perform signatures
26 | attr_accessor :provider
27 | end
28 |
29 | # Select the Ed25519::Provider to use based on the current environment
30 | if defined? JRUBY_VERSION
31 | require "jruby"
32 | require "ed25519_jruby"
33 | self.provider = org.cryptorb.Ed25519Provider.createEd25519Module(JRuby.runtime)
34 | else
35 | require "ed25519_ref10"
36 | self.provider = Ed25519::Provider::Ref10
37 | end
38 |
39 | # Ensure a serialized key meets the requirements
40 | def validate_key_bytes(key_bytes)
41 | raise TypeError, "expected String, got #{key_bytes.class}" unless key_bytes.is_a?(String)
42 | return true if key_bytes.bytesize == KEY_SIZE
43 |
44 | raise ArgumentError, "expected #{KEY_SIZE}-byte String, got #{key_bytes.bytesize}"
45 | end
46 |
47 | # Perform a self-test to ensure the selected provider is working
48 | def self_test
49 | signature_key = Ed25519::SigningKey.new("A" * 32)
50 | raise SelfTestFailure, "failed to generate verify key correctly" unless signature_key.verify_key.to_bytes.unpack1("H*") == "db995fe25169d141cab9bbba92baa01f9f2e1ece7df4cb2ac05190f37fcc1f9d"
51 |
52 | message = "crypto libraries should self-test on boot"
53 | signature = signature_key.sign(message)
54 | raise SelfTestFailure, "failed to generate correct signature" unless signature.unpack1("H*") == "c62c12a3a6cbfa04800d4be81468ef8aecd152a6a26a81d91257baecef13ba209531fe905a843e833c8b71cee04400fa2af3a29fef1152ece470421848758d0a"
55 |
56 | verify_key = signature_key.verify_key
57 | raise SelfTestFailure, "failed to verify a valid signature" unless verify_key.verify(signature, message)
58 |
59 | bad_signature = "#{signature[0...63]}X"
60 | ex = nil
61 | begin
62 | verify_key.verify(bad_signature, message)
63 | rescue Ed25519::VerifyError => ex
64 | end
65 |
66 | raise SelfTestFailure, "failed to detect an invalid signature" unless ex.is_a?(Ed25519::VerifyError)
67 | end
68 | end
69 | # rubocop:enable Layout/LineLength
70 |
71 | # Automatically run self-test when library loads
72 | Ed25519.self_test
73 |
--------------------------------------------------------------------------------
/lib/ed25519/signing_key.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 |
3 | require "securerandom"
4 |
5 | module Ed25519
6 | # Private key for producing digital signatures
7 | class SigningKey
8 | attr_reader :seed, :keypair, :verify_key
9 |
10 | # Generate a random Ed25519 signing key (i.e. private scalar)
11 | def self.generate
12 | new SecureRandom.random_bytes(Ed25519::KEY_SIZE)
13 | end
14 |
15 | # Create a SigningKey from a 64-byte Ed25519 keypair (i.e. public + private)
16 | #
17 | # @param keypair [String] 64-byte keypair value containing both seed + public key
18 | def self.from_keypair(keypair)
19 | raise TypeError, "expected String, got #{keypair.class}" unless keypair.is_a?(String)
20 | raise ArgumentError, "expected 64-byte String, got #{keypair.bytesize}" unless keypair.bytesize == 64
21 |
22 | new(keypair[0, KEY_SIZE]).tap do |key|
23 | raise ArgumentError, "corrupt keypair" unless keypair[KEY_SIZE, KEY_SIZE] == key.verify_key.to_bytes
24 | end
25 | end
26 |
27 | # Create a new Ed25519::SigningKey from the given seed value
28 | #
29 | # @param seed [String] 32-byte seed value from which the key should be derived
30 | def initialize(seed)
31 | Ed25519.validate_key_bytes(seed)
32 |
33 | @seed = seed
34 | @keypair = Ed25519.provider.create_keypair(seed)
35 | @verify_key = VerifyKey.new(@keypair[32, 32])
36 | end
37 |
38 | # Sign the given message, returning an Ed25519 signature
39 | #
40 | # @param message [String] message to be signed
41 | #
42 | # @return [String] 64-byte Ed25519 signature
43 | def sign(message)
44 | Ed25519.provider.sign(@keypair, message)
45 | end
46 |
47 | # String inspection that does not leak secret values
48 | def inspect
49 | to_s
50 | end
51 |
52 | # Return a bytestring representation of this signing key
53 | #
54 | # @return [String] signing key converted to a bytestring
55 | def to_bytes
56 | seed
57 | end
58 | alias to_str to_bytes
59 | end
60 | end
61 |
--------------------------------------------------------------------------------
/lib/ed25519/verify_key.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 |
3 | module Ed25519
4 | # Public key for verifying digital signatures
5 | class VerifyKey
6 | # Create a Ed25519::VerifyKey from its serialized Twisted Edwards representation
7 | #
8 | # @param key [String] 32-byte string representing a serialized public key
9 | def initialize(key)
10 | Ed25519.validate_key_bytes(key)
11 | @key_bytes = key
12 | end
13 |
14 | # Verify an Ed25519 signature against the message
15 | #
16 | # @param signature [String] 64-byte string containing an Ed25519 signature
17 | # @param message [String] string containing message to be verified
18 | #
19 | # @raise Ed25519::VerifyError signature verification failed
20 | #
21 | # @return [true] message verified successfully
22 | def verify(signature, message)
23 | if signature.length != SIGNATURE_SIZE
24 | raise ArgumentError, "expected #{SIGNATURE_SIZE} byte signature, got #{signature.length}"
25 | end
26 |
27 | return true if Ed25519.provider.verify(@key_bytes, signature, message)
28 |
29 | raise VerifyError, "signature verification failed!"
30 | end
31 |
32 | # Return a compressed twisted Edwards coordinate representing the public key
33 | #
34 | # @return [String] bytestring serialization of this public key
35 | def to_bytes
36 | @key_bytes
37 | end
38 | alias to_str to_bytes
39 |
40 | # Show hex representation of serialized coordinate in string inspection
41 | def inspect
42 | "#<#{self.class}:#{@key_bytes.unpack1('H*')}>"
43 | end
44 | end
45 | end
46 |
--------------------------------------------------------------------------------
/lib/ed25519/version.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 |
3 | module Ed25519
4 | VERSION = "1.4.0"
5 | end
6 |
--------------------------------------------------------------------------------
/spec/ed25519/provider/jruby_spec.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 |
3 | if defined?(JRUBY_VERSION)
4 | RSpec.describe Ed25519::Provider::JRuby do
5 | include_examples "Ed25519::Provider"
6 | end
7 | end
8 |
--------------------------------------------------------------------------------
/spec/ed25519/provider/ref10_spec.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 |
3 | unless defined?(JRUBY_VERSION)
4 | RSpec.describe Ed25519::Provider::Ref10 do
5 | include_examples "Ed25519::Provider"
6 | end
7 | end
8 |
--------------------------------------------------------------------------------
/spec/ed25519/signing_key_spec.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 |
3 | require "spec_helper"
4 |
5 | RSpec.describe Ed25519::SigningKey do
6 | let(:key) { described_class.generate }
7 | let(:message) { "example message" }
8 |
9 | describe ".generate" do
10 | it "generates keypairs" do
11 | expect(key).to be_a described_class
12 | expect(key.verify_key).to be_a Ed25519::VerifyKey
13 | end
14 | end
15 |
16 | describe ".from_keypair" do
17 | it "loads keypairs from bytes" do
18 | expect(described_class.from_keypair(key.keypair)).to be_a described_class
19 | end
20 |
21 | it "raises ArgumentError if given an invalid keypair" do
22 | expect { described_class.from_keypair("\0" * 64) }.to raise_error ArgumentError
23 | end
24 | end
25 |
26 | describe "#sign" do
27 | it "signs messages" do
28 | expect(key.sign(message)).to be_a String
29 | end
30 | end
31 |
32 | describe "#to_bytes" do
33 | it "serializes to bytes" do
34 | bytes = key.to_bytes
35 | expect(bytes).to be_a String
36 | expect(bytes.length).to eq Ed25519::KEY_SIZE
37 | end
38 | end
39 | end
40 |
--------------------------------------------------------------------------------
/spec/ed25519/test_vectors_spec.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 |
3 | # rubocop:disable Metrics/BlockLength
4 |
5 | require "spec_helper"
6 |
7 | RSpec.describe Ed25519::SigningKey do
8 | describe "RFC 8032 test vectors" do
9 | it "are handled correctly" do
10 | tests = [
11 | [<