2 * Copyright (c) 2017 Thomas Pornin <pornin@bolet.org>
4 * Permission is hereby granted, free of charge, to any person obtaining
5 * a copy of this software and associated documentation files (the
6 * "Software"), to deal in the Software without restriction, including
7 * without limitation the rights to use, copy, modify, merge, publish,
8 * distribute, sublicense, and/or sell copies of the Software, and to
9 * permit persons to whom the Software is furnished to do so, subject to
10 * the following conditions:
12 * The above copyright notice and this permission notice shall be
13 * included in all copies or substantial portions of the Software.
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
17 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
18 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
19 * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
20 * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
21 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
30 * Implementation for Curve25519.
33 internal class ECCurve25519 : ECCurve {
35 public override string Name {
41 public override ECCurveType CurveType {
43 return ECCurveType.Montgomery;
47 public override int EncodedLength {
53 public override int EncodedLengthCompressed {
59 public override byte[] GetGenerator(bool compressed)
61 byte[] G = new byte[32];
66 private static byte[] ORDER = {
67 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
68 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
69 0x14, 0xDE, 0xF9, 0xDE, 0xA2, 0xF7, 0x9C, 0xD6,
70 0x58, 0x12, 0x63, 0x1A, 0x5C, 0xF5, 0xD3, 0xED
73 private static byte[] COFACTOR = {
77 private static byte[] MOD = {
78 0x7F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
79 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
80 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
81 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xED
87 internal ECCurve25519() : base(ORDER, COFACTOR)
95 public override void CheckValid()
97 /* Nothing to do, the curve is valid by construction. */
100 public override int GetXoff(out int len)
107 public override uint Mul(byte[] G, byte[] x, byte[] D, bool compressed)
109 if (G.Length != 32 || D.Length != 32 || x.Length > 32) {
113 byte[] k = new byte[32];
114 Array.Copy(x, 0, k, 32 - x.Length, x.Length);
120 byte[] u = new byte[32];
121 for (int i = 0; i < 32; i ++) {
126 ModInt x1 = mp.Dup();
129 ModInt x2 = mp.Dup();
130 x2.SetMonty(0xFFFFFFFF);
131 ModInt z2 = mp.Dup();
132 ModInt x3 = x1.Dup();
133 ModInt z3 = x2.Dup();
137 ModInt aa = mp.Dup();
139 ModInt bb = mp.Dup();
144 for (int t = 254; t >= 0; t --) {
145 uint kt = (uint)-((k[31 - (t >> 3)] >> (t & 7)) & 1);
147 x2.CondSwap(x3, swap);
148 z2.CondSwap(z3, swap);
181 x2.CondSwap(x3, swap);
182 z2.CondSwap(z3, swap);
189 for (int i = 0; i < 32; i ++) {
195 public override uint MulAdd(byte[] A, byte[] x, byte[] B, byte[] y,
196 byte[] D, bool compressed)
198 throw new CryptoException(
199 "Operation not supported for Curve25519");
203 public override bool Equals(object obj)
205 return (obj as ECCurve25519) != null;
208 public override int GetHashCode()
213 public override byte[] MakeRandomSecret()
216 * For Curve25519, we simply generate a random 32-byte
217 * array, to which we apply the "clamping" that will
218 * be done for point multiplication anyway.
220 byte[] x = new byte[32];
228 internal override MutableECPoint MakeZero()
230 return new MutableECPointCurve25519();
233 internal override MutableECPoint MakeGenerator()
235 MutableECPointCurve25519 G = new MutableECPointCurve25519();
236 G.Decode(GetGenerator(false));
240 internal override MutableECPoint Decode(byte[] enc)
242 MutableECPointCurve25519 P = new MutableECPointCurve25519();