1
0
mirror of https://github.com/henrydcase/nobs.git synced 2024-11-22 23:28:57 +00:00
nobs/dh/csidh/consts.go
Kris Kwiatkowski 7efbbf4745 cSIDH-511: (#26)
Implementation of Commutative Supersingular Isogeny Diffie Hellman,
based on "A faster way to CSIDH" paper (2018/782).

* For fast isogeny calculation, implementation converts a curve from
  Montgomery to Edwards. All calculations are done on Edwards curve
  and then converted back to Montgomery.
* As multiplication in a field Fp511 is most expensive operation
  the implementation contains multiple multiplications. It has
  most performant, assembly implementation which uses BMI2 and
  ADOX/ADCX instructions for modern CPUs. It also contains
  slower implementation which will run on older CPUs

* Benchmarks (Intel SkyLake):

  BenchmarkGeneratePrivate   	    6459	    172213 ns/op	       0 B/op	       0 allocs/op
  BenchmarkGenerateKeyPair   	      25	  45800356 ns/op	       0 B/op	       0 allocs/op
  BenchmarkValidate          	     297	   3915983 ns/op	       0 B/op	       0 allocs/op
  BenchmarkValidateRandom    	  184683	      6231 ns/op	       0 B/op	       0 allocs/op
  BenchmarkValidateGenerated 	      25	  48481306 ns/op	       0 B/op	       0 allocs/op
  BenchmarkDerive            	      19	  60928763 ns/op	       0 B/op	       0 allocs/op
  BenchmarkDeriveGenerated   	       8	 137342421 ns/op	       0 B/op	       0 allocs/op
  BenchmarkXMul              	    2311	    494267 ns/op	       1 B/op	       0 allocs/op
  BenchmarkXAdd              	 2396754	       501 ns/op	       0 B/op	       0 allocs/op
  BenchmarkXDbl              	 2072690	       571 ns/op	       0 B/op	       0 allocs/op
  BenchmarkIsom              	   78004	     15171 ns/op	       0 B/op	       0 allocs/op
  BenchmarkFp512Sub          	224635152	         5.33 ns/op	       0 B/op	       0 allocs/op
  BenchmarkFp512Mul          	246633255	         4.90 ns/op	       0 B/op	       0 allocs/op
  BenchmarkCSwap             	233228547	         5.10 ns/op	       0 B/op	       0 allocs/op
  BenchmarkAddRdc            	87348240	        12.6 ns/op	       0 B/op	       0 allocs/op
  BenchmarkSubRdc            	95112787	        11.7 ns/op	       0 B/op	       0 allocs/op
  BenchmarkModExpRdc         	   25436	     46878 ns/op	       0 B/op	       0 allocs/op
  BenchmarkMulBmiAsm         	19527573	        60.1 ns/op	       0 B/op	       0 allocs/op
  BenchmarkMulGeneric        	 7117650	       164 ns/op	       0 B/op	       0 allocs/op

* Go code has very similar performance when compared to C
  implementation.
  Results from sidh_torturer (4e2996e12d68364761064341cbe1d1b47efafe23)
  github.com:henrydcase/sidh-torture/csidh

  | TestName         |Go        | C        |
  |------------------|----------|----------|
  |TestSharedSecret  | 57.95774 | 57.91092 |
  |TestKeyGeneration | 62.23614 | 58.12980 |
  |TestSharedSecret  | 55.28988 | 57.23132 |
  |TestKeyGeneration | 61.68745 | 58.66396 |
  |TestSharedSecret  | 63.19408 | 58.64774 |
  |TestKeyGeneration | 62.34022 | 61.62539 |
  |TestSharedSecret  | 62.85453 | 68.74503 |
  |TestKeyGeneration | 52.58518 | 58.40115 |
  |TestSharedSecret  | 50.77081 | 61.91699 |
  |TestKeyGeneration | 59.91843 | 61.09266 |
  |TestSharedSecret  | 59.97962 | 62.98151 |
  |TestKeyGeneration | 64.57525 | 56.22863 |
  |TestSharedSecret  | 56.40521 | 55.77447 |
  |TestKeyGeneration | 67.85850 | 58.52604 |
  |TestSharedSecret  | 60.54290 | 65.14052 |
  |TestKeyGeneration | 65.45766 | 58.42823 |

  On average Go implementation is 2% faster.
2019-11-25 15:03:29 +00:00

105 lines
3.0 KiB
Go

package csidh
const (
// pbits is a bitsize of prime p
pbits = 511
// primeCount number of Elkies primes used for constructing p
primeCount = 74
// (2*5+1)^74 is roughly 2^256
expMax = int8(5)
// size of the limbs, pretty much hardcoded to 64-bit words
limbBitSize = 64
// size of the limbs in bytes
limbByteSize = limbBitSize >> 3
// Number of limbs for a field element
numWords = 8
// PrivateKeySize is a size of cSIDH/512 private key in bytes.
PrivateKeySize = 37
// PublicKeySize is a size of cSIDH/512 public key in bytes.
PublicKeySize = 64
// SharedSecretSize is a size of cSIDH/512 shared secret in bytes.
SharedSecretSize = 64
)
var (
// Elkies primes up to 374 + prime 587
// p = 4 * product(primes) - 1
primes = [primeCount]uint64{
0x0003, 0x0005, 0x0007, 0x000B, 0x000D, 0x0011, 0x0013, 0x0017, 0x001D, 0x001F, 0x0025,
0x0029, 0x002B, 0x002F, 0x0035, 0x003B, 0x003D, 0x0043, 0x0047, 0x0049, 0x004F, 0x0053,
0x0059, 0x0061, 0x0065, 0x0067, 0x006B, 0x006D, 0x0071, 0x007F, 0x0083, 0x0089, 0x008B,
0x0095, 0x0097, 0x009D, 0x00A3, 0x00A7, 0x00AD, 0x00B3, 0x00B5, 0x00BF, 0x00C1, 0x00C5,
0x00C7, 0x00D3, 0x00DF, 0x00E3, 0x00E5, 0x00E9, 0x00EF, 0x00F1, 0x00FB, 0x0101, 0x0107,
0x010D, 0x010F, 0x0115, 0x0119, 0x011B, 0x0125, 0x0133, 0x0137, 0x0139, 0x013D, 0x014B,
0x0151, 0x015B, 0x015D, 0x0161, 0x0167, 0x016F, 0x0175, 0x024B}
p = fp{
0x1B81B90533C6C87B, 0xC2721BF457ACA835,
0x516730CC1F0B4F25, 0xA7AAC6C567F35507,
0x5AFBFCC69322C9CD, 0xB42D083AEDC88C42,
0xFC8AB0D15E3E4C4A, 0x65B48E8F740F89BF,
}
/* Montgomery R = 2^512 mod p */
one = fp{
0xC8FC8DF598726F0A, 0x7B1BC81750A6AF95,
0x5D319E67C1E961B4, 0xB0AA7275301955F1,
0x4A080672D9BA6C64, 0x97A5EF8A246EE77B,
0x06EA9E5D4383676A, 0x3496E2E117E0EC80,
}
// 2 in Montgomery domain
two = fp{
0x767762E5FD1E1599, 0x33C5743A49A0B6F6,
0x68FC0C0364C77443, 0xB9AA1E24F83F56DB,
0x3914101F20520EFB, 0x7B1ED6D95B1542B4,
0x114A8BE928C8828A, 0x03793732BBB24F40,
}
// -2 in Montgomery domain
twoNeg = fp{
0xA50A561F36A8B2E2, 0x8EACA7BA0E0BF13E,
0xE86B24C8BA43DAE2, 0xEE00A8A06FB3FE2B,
0x21E7ECA772D0BAD1, 0x390E316192B3498E,
0xEB4024E83575C9C0, 0x623B575CB85D3A7F,
}
// 4 in Montgomery domain
four = fp{
0xECEEC5CBFA3C2B32, 0x678AE87493416DEC,
0xD1F81806C98EE886, 0x73543C49F07EADB6,
0x7228203E40A41DF7, 0xF63DADB2B62A8568,
0x229517D251910514, 0x06F26E6577649E80,
}
// 4 * sqrt(p)
fourSqrtP = fp{
0x17895E71E1A20B3F, 0x38D0CD95F8636A56,
0x142B9541E59682CD, 0x856F1399D91D6592,
0x0000000000000002,
}
// -p^-1 mod 2^64
pNegInv = fp{
0x66c1301f632e294d,
}
// (p-1)/2. Used as exponent, hence not in
// montgomery domain
pMin1By2 = fp{
0x8DC0DC8299E3643D, 0xE1390DFA2BD6541A,
0xA8B398660F85A792, 0xD3D56362B3F9AA83,
0x2D7DFE63499164E6, 0x5A16841D76E44621,
0xFE455868AF1F2625, 0x32DA4747BA07C4DF,
}
// p-1 mod 2^64. Used as exponent, hence not
// in montgomery domain
pMin1 = fp{
0x1B81B90533C6C879, 0xC2721BF457ACA835,
0x516730CC1F0B4F25, 0xA7AAC6C567F35507,
0x5AFBFCC69322C9CD, 0xB42D083AEDC88C42,
0xFC8AB0D15E3E4C4A, 0x65B48E8F740F89BF,
}
)