| Index: third_party/tlslite/patches/ecdhe_rsa.patch
|
| diff --git a/third_party/tlslite/patches/ecdhe_rsa.patch b/third_party/tlslite/patches/ecdhe_rsa.patch
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..054a07a0f0553a71849728eb034799e8cc53a3c7
|
| --- /dev/null
|
| +++ b/third_party/tlslite/patches/ecdhe_rsa.patch
|
| @@ -0,0 +1,428 @@
|
| +diff --git a/third_party/tlslite/tlslite/constants.py b/third_party/tlslite/tlslite/constants.py
|
| +index e5b88af..6d78a20 100644
|
| +--- a/third_party/tlslite/tlslite/constants.py
|
| ++++ b/third_party/tlslite/tlslite/constants.py
|
| +@@ -76,6 +76,14 @@ class SignatureAlgorithm:
|
| + class NameType:
|
| + host_name = 0
|
| +
|
| ++class ECCurveType:
|
| ++ explicit_prime = 1
|
| ++ explicit_char2 = 2
|
| ++ named_curve = 3
|
| ++
|
| ++class NamedCurve:
|
| ++ secp256r1 = 23
|
| ++
|
| + class AlertLevel:
|
| + warning = 1
|
| + fatal = 2
|
| +@@ -178,11 +186,19 @@ class CipherSuite:
|
| + TLS_RSA_WITH_AES_128_GCM_SHA256 = 0x009C
|
| + TLS_DHE_RSA_WITH_AES_128_GCM_SHA256 = 0x009E
|
| +
|
| ++ TLS_ECDHE_RSA_WITH_RC4_128_SHA = 0xc011
|
| ++ TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA = 0xc012
|
| ++ TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA = 0xc013
|
| ++ TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA = 0xc014
|
| ++ TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256 = 0xc027
|
| ++ TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 = 0xc02f
|
| ++
|
| + tripleDESSuites = []
|
| + tripleDESSuites.append(TLS_SRP_SHA_WITH_3DES_EDE_CBC_SHA)
|
| + tripleDESSuites.append(TLS_SRP_SHA_RSA_WITH_3DES_EDE_CBC_SHA)
|
| + tripleDESSuites.append(TLS_RSA_WITH_3DES_EDE_CBC_SHA)
|
| + tripleDESSuites.append(TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA)
|
| ++ tripleDESSuites.append(TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA)
|
| +
|
| + aes128Suites = []
|
| + aes128Suites.append(TLS_SRP_SHA_WITH_AES_128_CBC_SHA)
|
| +@@ -192,6 +208,8 @@ class CipherSuite:
|
| + aes128Suites.append(TLS_DH_ANON_WITH_AES_128_CBC_SHA)
|
| + aes128Suites.append(TLS_RSA_WITH_AES_128_CBC_SHA256)
|
| + aes128Suites.append(TLS_DHE_RSA_WITH_AES_128_CBC_SHA256)
|
| ++ aes128Suites.append(TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA)
|
| ++ aes128Suites.append(TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256)
|
| +
|
| + aes256Suites = []
|
| + aes256Suites.append(TLS_SRP_SHA_WITH_AES_256_CBC_SHA)
|
| +@@ -201,14 +219,17 @@ class CipherSuite:
|
| + aes256Suites.append(TLS_DHE_RSA_WITH_AES_256_CBC_SHA)
|
| + aes256Suites.append(TLS_RSA_WITH_AES_256_CBC_SHA256)
|
| + aes256Suites.append(TLS_DHE_RSA_WITH_AES_256_CBC_SHA256)
|
| ++ aes256Suites.append(TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA)
|
| +
|
| + aes128GcmSuites = []
|
| + aes128GcmSuites.append(TLS_RSA_WITH_AES_128_GCM_SHA256)
|
| + aes128GcmSuites.append(TLS_DHE_RSA_WITH_AES_128_GCM_SHA256)
|
| ++ aes128GcmSuites.append(TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256)
|
| +
|
| + rc4Suites = []
|
| + rc4Suites.append(TLS_RSA_WITH_RC4_128_SHA)
|
| + rc4Suites.append(TLS_RSA_WITH_RC4_128_MD5)
|
| ++ rc4Suites.append(TLS_ECDHE_RSA_WITH_RC4_128_SHA)
|
| +
|
| + shaSuites = []
|
| + shaSuites.append(TLS_SRP_SHA_WITH_3DES_EDE_CBC_SHA)
|
| +@@ -226,6 +247,10 @@ class CipherSuite:
|
| + shaSuites.append(TLS_DHE_RSA_WITH_AES_256_CBC_SHA)
|
| + shaSuites.append(TLS_DH_ANON_WITH_AES_128_CBC_SHA)
|
| + shaSuites.append(TLS_DH_ANON_WITH_AES_256_CBC_SHA)
|
| ++ shaSuites.append(TLS_ECDHE_RSA_WITH_RC4_128_SHA)
|
| ++ shaSuites.append(TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA)
|
| ++ shaSuites.append(TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA)
|
| ++ shaSuites.append(TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA)
|
| +
|
| + sha256Suites = []
|
| + sha256Suites.append(TLS_RSA_WITH_AES_128_CBC_SHA256)
|
| +@@ -234,6 +259,9 @@ class CipherSuite:
|
| + sha256Suites.append(TLS_DHE_RSA_WITH_AES_256_CBC_SHA256)
|
| + sha256Suites.append(TLS_RSA_WITH_AES_128_GCM_SHA256)
|
| + sha256Suites.append(TLS_DHE_RSA_WITH_AES_128_GCM_SHA256)
|
| ++ sha256Suites.append(TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256)
|
| ++ sha256Suites.append(TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256)
|
| ++
|
| +
|
| + aeadSuites = aes128GcmSuites
|
| +
|
| +@@ -275,6 +303,8 @@ class CipherSuite:
|
| + keyExchangeSuites += CipherSuite.certSuites
|
| + if "dhe_rsa" in keyExchangeNames:
|
| + keyExchangeSuites += CipherSuite.dheCertSuites
|
| ++ if "ecdhe_rsa" in keyExchangeNames:
|
| ++ keyExchangeSuites += CipherSuite.ecdheCertSuites
|
| + if "srp_sha" in keyExchangeNames:
|
| + keyExchangeSuites += CipherSuite.srpSuites
|
| + if "srp_sha_rsa" in keyExchangeNames:
|
| +@@ -335,7 +365,19 @@ class CipherSuite:
|
| + def getDheCertSuites(settings, version=None):
|
| + return CipherSuite._filterSuites(CipherSuite.dheCertSuites, settings, version)
|
| +
|
| +- certAllSuites = srpCertSuites + certSuites + dheCertSuites
|
| ++ ecdheCertSuites = []
|
| ++ ecdheCertSuites.append(TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256)
|
| ++ ecdheCertSuites.append(TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256)
|
| ++ ecdheCertSuites.append(TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA)
|
| ++ ecdheCertSuites.append(TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA)
|
| ++ ecdheCertSuites.append(TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA)
|
| ++ ecdheCertSuites.append(TLS_ECDHE_RSA_WITH_RC4_128_SHA)
|
| ++
|
| ++ @staticmethod
|
| ++ def getEcdheCertSuites(settings, version=None):
|
| ++ return CipherSuite._filterSuites(CipherSuite.ecdheCertSuites, settings, version)
|
| ++
|
| ++ certAllSuites = srpCertSuites + certSuites + dheCertSuites + ecdheCertSuites
|
| +
|
| + anonSuites = []
|
| + anonSuites.append(TLS_DH_ANON_WITH_AES_256_CBC_SHA)
|
| +@@ -346,6 +388,7 @@ class CipherSuite:
|
| + return CipherSuite._filterSuites(CipherSuite.anonSuites, settings, version)
|
| +
|
| + dhAllSuites = dheCertSuites + anonSuites
|
| ++ ecdhAllSuites = ecdheCertSuites
|
| +
|
| + @staticmethod
|
| + def canonicalCipherName(ciphersuite):
|
| +diff --git a/third_party/tlslite/tlslite/handshakesettings.py b/third_party/tlslite/tlslite/handshakesettings.py
|
| +index e752834..605ed42 100644
|
| +--- a/third_party/tlslite/tlslite/handshakesettings.py
|
| ++++ b/third_party/tlslite/tlslite/handshakesettings.py
|
| +@@ -14,7 +14,7 @@ from .utils import cipherfactory
|
| + CIPHER_NAMES = ["aes128gcm", "rc4", "aes256", "aes128", "3des"]
|
| + MAC_NAMES = ["sha", "sha256", "aead"] # Don't allow "md5" by default.
|
| + ALL_MAC_NAMES = MAC_NAMES + ["md5"]
|
| +-KEY_EXCHANGE_NAMES = ["rsa", "dhe_rsa", "srp_sha", "srp_sha_rsa", "dh_anon"]
|
| ++KEY_EXCHANGE_NAMES = ["rsa", "dhe_rsa", "ecdhe_rsa", "srp_sha", "srp_sha_rsa", "dh_anon"]
|
| + CIPHER_IMPLEMENTATIONS = ["openssl", "pycrypto", "python"]
|
| + CERTIFICATE_TYPES = ["x509"]
|
| + TLS_INTOLERANCE_TYPES = ["alert", "close", "reset"]
|
| +diff --git a/third_party/tlslite/tlslite/messages.py b/third_party/tlslite/tlslite/messages.py
|
| +index f2e2cfc..9aeff6d 100644
|
| +--- a/third_party/tlslite/tlslite/messages.py
|
| ++++ b/third_party/tlslite/tlslite/messages.py
|
| +@@ -509,10 +509,13 @@ class ServerKeyExchange(HandshakeMsg):
|
| + self.srp_g = 0
|
| + self.srp_s = bytearray(0)
|
| + self.srp_B = 0
|
| +- # Anon DH params:
|
| ++ # DH params:
|
| + self.dh_p = 0
|
| + self.dh_g = 0
|
| + self.dh_Ys = 0
|
| ++ # ECDH params:
|
| ++ self.ecdhCurve = 0
|
| ++ self.ecdhPublic = bytearray(0)
|
| + self.signature = bytearray(0)
|
| +
|
| + def createSRP(self, srp_N, srp_g, srp_s, srp_B):
|
| +@@ -528,6 +531,11 @@ class ServerKeyExchange(HandshakeMsg):
|
| + self.dh_Ys = dh_Ys
|
| + return self
|
| +
|
| ++ def createECDH(self, ecdhCurve, ecdhPublic):
|
| ++ self.ecdhCurve = ecdhCurve
|
| ++ self.ecdhPublic = ecdhPublic
|
| ++ return self
|
| ++
|
| + def parse(self, p):
|
| + p.startLengthCheck(3)
|
| + if self.cipherSuite in CipherSuite.srpAllSuites:
|
| +@@ -555,6 +563,10 @@ class ServerKeyExchange(HandshakeMsg):
|
| + w.addVarSeq(numberToByteArray(self.dh_p), 1, 2)
|
| + w.addVarSeq(numberToByteArray(self.dh_g), 1, 2)
|
| + w.addVarSeq(numberToByteArray(self.dh_Ys), 1, 2)
|
| ++ elif self.cipherSuite in CipherSuite.ecdhAllSuites:
|
| ++ w.add(ECCurveType.named_curve, 1)
|
| ++ w.add(self.ecdhCurve, 2)
|
| ++ w.addVarSeq(self.ecdhPublic, 1, 1)
|
| + else:
|
| + assert(False)
|
| + return w.bytes
|
| +@@ -626,7 +638,9 @@ class ClientKeyExchange(HandshakeMsg):
|
| + else:
|
| + raise AssertionError()
|
| + elif self.cipherSuite in CipherSuite.dhAllSuites:
|
| +- self.dh_Yc = bytesToNumber(p.getVarBytes(2))
|
| ++ self.dh_Yc = bytesToNumber(p.getVarBytes(2))
|
| ++ elif self.cipherSuite in CipherSuite.ecdhAllSuites:
|
| ++ self.ecdh_Yc = p.getVarBytes(1)
|
| + else:
|
| + raise AssertionError()
|
| + p.stopLengthCheck()
|
| +diff --git a/third_party/tlslite/tlslite/tlsconnection.py b/third_party/tlslite/tlslite/tlsconnection.py
|
| +index 0a85d3c..dfac274 100644
|
| +--- a/third_party/tlslite/tlslite/tlsconnection.py
|
| ++++ b/third_party/tlslite/tlslite/tlsconnection.py
|
| +@@ -24,6 +24,7 @@ from .mathtls import *
|
| + from .handshakesettings import HandshakeSettings
|
| + from .utils.tackwrapper import *
|
| + from .utils.rsakey import RSAKey
|
| ++from .utils import p256
|
| +
|
| + class KeyExchange(object):
|
| + def __init__(self, cipherSuite, clientHello, serverHello, privateKey):
|
| +@@ -127,6 +128,25 @@ DE2BCBF6 95581718 3995497C EA956AE5 15D22618 98FA0510
|
| + S = powMod(dh_Yc, self.dh_Xs, self.dh_p)
|
| + return numberToByteArray(S)
|
| +
|
| ++class ECDHE_RSAKeyExchange(KeyExchange):
|
| ++ def makeServerKeyExchange(self):
|
| ++ public, self.private = p256.generatePublicPrivate()
|
| ++
|
| ++ version = self.serverHello.server_version
|
| ++ serverKeyExchange = ServerKeyExchange(self.cipherSuite, version)
|
| ++ serverKeyExchange.createECDH(NamedCurve.secp256r1, bytearray(public))
|
| ++ hashBytes = serverKeyExchange.hash(self.clientHello.random,
|
| ++ self.serverHello.random)
|
| ++ if version >= (3,3):
|
| ++ # TODO: Signature algorithm negotiation not supported.
|
| ++ hashBytes = RSAKey.addPKCS1SHA1Prefix(hashBytes)
|
| ++ serverKeyExchange.signature = self.privateKey.sign(hashBytes)
|
| ++ return serverKeyExchange
|
| ++
|
| ++ def processClientKeyExchange(self, clientKeyExchange):
|
| ++ ecdh_Yc = clientKeyExchange.ecdh_Yc
|
| ++ return bytearray(p256.generateSharedValue(bytes(ecdh_Yc), self.private))
|
| ++
|
| + class TLSConnection(TLSRecordLayer):
|
| + """
|
| + This class wraps a socket and provides TLS handshaking and data
|
| +@@ -1321,9 +1341,8 @@ class TLSConnection(TLSRecordLayer):
|
| + else: break
|
| + premasterSecret = result
|
| +
|
| +- # Perform the RSA or DHE_RSA key exchange
|
| +- elif (cipherSuite in CipherSuite.certSuites or
|
| +- cipherSuite in CipherSuite.dheCertSuites):
|
| ++ # Perform a certificate-based key exchange
|
| ++ elif cipherSuite in CipherSuite.certAllSuites:
|
| + if cipherSuite in CipherSuite.certSuites:
|
| + keyExchange = RSAKeyExchange(cipherSuite,
|
| + clientHello,
|
| +@@ -1334,6 +1353,11 @@ class TLSConnection(TLSRecordLayer):
|
| + clientHello,
|
| + serverHello,
|
| + privateKey)
|
| ++ elif cipherSuite in CipherSuite.ecdheCertSuites:
|
| ++ keyExchange = ECDHE_RSAKeyExchange(cipherSuite,
|
| ++ clientHello,
|
| ++ serverHello,
|
| ++ privateKey)
|
| + else:
|
| + assert(False)
|
| + for result in self._serverCertKeyExchange(clientHello, serverHello,
|
| +@@ -1450,6 +1474,7 @@ class TLSConnection(TLSRecordLayer):
|
| + CipherSuite.getSrpCertSuites(settings, self.version)
|
| + cipherSuites += CipherSuite.getSrpSuites(settings, self.version)
|
| + elif certChain:
|
| ++ cipherSuites += CipherSuite.getEcdheCertSuites(settings, self.version)
|
| + cipherSuites += CipherSuite.getDheCertSuites(settings, self.version)
|
| + cipherSuites += CipherSuite.getCertSuites(settings, self.version)
|
| + elif anon:
|
| +diff --git a/third_party/tlslite/tlslite/utils/p256.py b/third_party/tlslite/tlslite/utils/p256.py
|
| +index e69de29..6eb9a77 100644
|
| +--- a/third_party/tlslite/tlslite/utils/p256.py
|
| ++++ b/third_party/tlslite/tlslite/utils/p256.py
|
| +@@ -0,0 +1,162 @@
|
| ++# Author: Google
|
| ++# See the LICENSE file for legal information regarding use of this file.
|
| ++
|
| ++import os
|
| ++
|
| ++p = (
|
| ++ 115792089210356248762697446949407573530086143415290314195533631308867097853951)
|
| ++order = (
|
| ++ 115792089210356248762697446949407573529996955224135760342422259061068512044369)
|
| ++p256B = 0x5ac635d8aa3a93e7b3ebbd55769886bc651d06b0cc53b0f63bce3c3e27d2604b
|
| ++
|
| ++baseX = 0x6b17d1f2e12c4247f8bce6e563a440f277037d812deb33a0f4a13945d898c296
|
| ++baseY = 0x4fe342e2fe1a7f9b8ee7eb4a7c0f9e162bce33576b315ececbb6406837bf51f5
|
| ++basePoint = (baseX, baseY)
|
| ++
|
| ++
|
| ++def _pointAdd(a, b):
|
| ++ Z1Z1 = (a[2] * a[2]) % p
|
| ++ Z2Z2 = (b[2] * b[2]) % p
|
| ++ U1 = (a[0] * Z2Z2) % p
|
| ++ U2 = (b[0] * Z1Z1) % p
|
| ++ S1 = (a[1] * b[2] * Z2Z2) % p
|
| ++ S2 = (b[1] * a[2] * Z1Z1) % p
|
| ++ if U1 == U2 and S1 == S2:
|
| ++ return pointDouble(a)
|
| ++ H = (U2 - U1) % p
|
| ++ I = (4 * H * H) % p
|
| ++ J = (H * I) % p
|
| ++ r = (2 * (S2 - S1)) % p
|
| ++ V = (U1 * I) % p
|
| ++ X3 = (r * r - J - 2 * V) % p
|
| ++ Y3 = (r * (V - X3) - 2 * S1 * J) % p
|
| ++ Z3 = (((a[2] + b[2]) * (a[2] + b[2]) - Z1Z1 - Z2Z2) * H) % p
|
| ++
|
| ++ return (X3, Y3, Z3)
|
| ++
|
| ++
|
| ++def _pointDouble(a):
|
| ++ delta = (a[2] * a[2]) % p
|
| ++ gamma = (a[1] * a[1]) % p
|
| ++ beta = (a[0] * gamma) % p
|
| ++ alpha = (3 * (a[0] - delta) * (a[0] + delta)) % p
|
| ++ X3 = (alpha * alpha - 8 * beta) % p
|
| ++ Z3 = ((a[1] + a[2]) * (a[1] + a[2]) - gamma - delta) % p
|
| ++ Y3 = (alpha * (4 * beta - X3) - 8 * gamma * gamma) % p
|
| ++
|
| ++ return (X3, Y3, Z3)
|
| ++
|
| ++
|
| ++def _square(n):
|
| ++ return (n * n)
|
| ++
|
| ++
|
| ++def _modpow(a, n, p):
|
| ++ if n == 0:
|
| ++ return 1
|
| ++ if n == 1:
|
| ++ return a
|
| ++ r = _square(_modpow(a, n >> 1, p)) % p
|
| ++ if n & 1 == 1:
|
| ++ r = (r * a) % p
|
| ++ return r
|
| ++
|
| ++
|
| ++def _scalarMult(k, point):
|
| ++ accum = (0, 0, 0)
|
| ++ accumIsInfinity = True
|
| ++ jacobianPoint = (point[0], point[1], 1)
|
| ++
|
| ++ for bit in range(255, -1, -1):
|
| ++ if not accumIsInfinity:
|
| ++ accum = _pointDouble(accum)
|
| ++
|
| ++ if (k >> bit) & 1 == 1:
|
| ++ if accumIsInfinity:
|
| ++ accum = jacobianPoint
|
| ++ accumIsInfinity = False
|
| ++ else:
|
| ++ accum = _pointAdd(accum, jacobianPoint)
|
| ++
|
| ++ if accumIsInfinity:
|
| ++ return (0, 0)
|
| ++
|
| ++ zInv = _modpow(accum[2], p - 2, p)
|
| ++ return ((accum[0] * zInv * zInv) % p, (accum[1] * zInv * zInv * zInv) % p)
|
| ++
|
| ++
|
| ++def _scalarBaseMult(k):
|
| ++ return _scalarMult(k, basePoint)
|
| ++
|
| ++
|
| ++def _decodeBigEndian(b):
|
| ++ return sum([ord(b[len(b) - i - 1]) << 8 * i for i in range(len(b))])
|
| ++
|
| ++
|
| ++def _encodeBigEndian(n):
|
| ++ b = []
|
| ++ while n != 0:
|
| ++ b.append(chr(n & 0xff))
|
| ++ n >>= 8
|
| ++
|
| ++ if len(b) == 0:
|
| ++ b.append(0)
|
| ++ b.reverse()
|
| ++
|
| ++ return "".join(b)
|
| ++
|
| ++
|
| ++def _zeroPad(b, length):
|
| ++ if len(b) < length:
|
| ++ return ("\x00" * (length - len(b))) + b
|
| ++ return b
|
| ++
|
| ++
|
| ++def _encodePoint(point):
|
| ++ x = point[0]
|
| ++ y = point[1]
|
| ++ if (y * y) % p != (x * x * x - 3 * x + p256B) % p:
|
| ++ raise "point not on curve"
|
| ++ return "\x04" + _zeroPad(_encodeBigEndian(point[0]), 32) + _zeroPad(
|
| ++ _encodeBigEndian(point[1]), 32)
|
| ++
|
| ++
|
| ++def _decodePoint(b):
|
| ++ if len(b) != 1 + 32 + 32 or ord(b[0]) != 4:
|
| ++ raise "invalid encoded ec point"
|
| ++ x = _decodeBigEndian(b[1:33])
|
| ++ y = _decodeBigEndian(b[33:65])
|
| ++ if (y * y) % p != (x * x * x - 3 * x + p256B) % p:
|
| ++ raise "point not on curve"
|
| ++ return (x, y)
|
| ++
|
| ++
|
| ++def generatePublicPrivate():
|
| ++ """generatePublicPrivate returns a tuple of (X9.62 encoded public point,
|
| ++ private value), where the private value is generated from os.urandom."""
|
| ++ private = _decodeBigEndian(os.urandom(40)) % order
|
| ++ return _encodePoint(_scalarBaseMult(private)), private
|
| ++
|
| ++
|
| ++def generateSharedValue(theirPublic, private):
|
| ++ """generateSharedValue returns the encoded x-coordinate of the
|
| ++ multiplication of a peer's X9.62 encoded point and a private value."""
|
| ++ return _zeroPad(
|
| ++ _encodeBigEndian(_scalarMult(private, _decodePoint(theirPublic))[0]),
|
| ++ 32)
|
| ++
|
| ++if __name__ == "__main__":
|
| ++ alice, alicePrivate = generatePublicPrivate()
|
| ++ bob, bobPrivate = generatePublicPrivate()
|
| ++
|
| ++ if generateSharedValue(alice, bobPrivate) != generateSharedValue(
|
| ++ bob, alicePrivate):
|
| ++ raise "simple DH test failed"
|
| ++
|
| ++ (x, _) = _scalarBaseMult(1)
|
| ++
|
| ++ for i in range(1000):
|
| ++ (x, _) = _scalarBaseMult(x)
|
| ++
|
| ++ if x != 2428281965257598569040586318034812501729437946720808289049534492833635302706:
|
| ++ raise "loop test failed"
|
|
|