Added internal python-only implementation of Ed25519
This commit is contained in:
		
							parent
							
								
									34efbc6100
								
							
						
					
					
						commit
						e0b795b4d0
					
				
							
								
								
									
										41
									
								
								RNS/Cryptography/Ed25519.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										41
									
								
								RNS/Cryptography/Ed25519.py
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,41 @@ | ||||
| import os | ||||
| from .pure25519 import ed25519_oop as ed25519 | ||||
| 
 | ||||
| class Ed25519PrivateKey: | ||||
|     def __init__(self, seed): | ||||
|         self.seed = seed | ||||
|         self.sk = ed25519.SigningKey(self.seed) | ||||
|         #self.vk = self.sk.get_verifying_key() | ||||
| 
 | ||||
|     @classmethod | ||||
|     def generate(cls): | ||||
|         return cls.from_private_bytes(os.urandom(32)) | ||||
| 
 | ||||
|     @classmethod | ||||
|     def from_private_bytes(cls, data): | ||||
|         return cls(seed=data) | ||||
| 
 | ||||
|     def private_bytes(self): | ||||
|         return self.seed | ||||
| 
 | ||||
|     def public_key(self): | ||||
|         return Ed25519PublicKey.from_public_bytes(self.sk.vk_s) | ||||
| 
 | ||||
|     def sign(self, message): | ||||
|         return self.sk.sign(message) | ||||
| 
 | ||||
| 
 | ||||
| class Ed25519PublicKey: | ||||
|     def __init__(self, seed): | ||||
|         self.seed = seed | ||||
|         self.vk = ed25519.VerifyingKey(self.seed) | ||||
| 
 | ||||
|     @classmethod | ||||
|     def from_public_bytes(cls, data): | ||||
|         return cls(data) | ||||
| 
 | ||||
|     def public_bytes(self): | ||||
|         return self.vk.to_bytes() | ||||
| 
 | ||||
|     def verify(self, signature, message): | ||||
|         self.vk.verify(signature, message) | ||||
| @ -1,14 +1,20 @@ | ||||
| import hashlib | ||||
| 
 | ||||
| """ | ||||
| The SHA primitives are abstracted here to allow platform- | ||||
| aware hardware acceleration in the future. Currently only | ||||
| uses Python's internal SHA-256 implementation. All SHA-256 | ||||
| calls in RNS end up here. | ||||
| """ | ||||
| 
 | ||||
| def sha256(data): | ||||
|     """ | ||||
|     The SHA-256 primitive is abstracted here to allow platform- | ||||
|     aware hardware acceleration in the future. Currently only | ||||
|     uses Python's internal SHA-256 implementation. All SHA-256 | ||||
|     calls in RNS end up here. | ||||
|     """ | ||||
|     digest = hashlib.sha256() | ||||
|     digest.update(data) | ||||
| 
 | ||||
|     return digest.digest() | ||||
|     return digest.digest() | ||||
| 
 | ||||
| def sha512(data): | ||||
|     digest = hashlib.sha512() | ||||
|     digest.update(data) | ||||
| 
 | ||||
|     return digest.digest() | ||||
|  | ||||
| @ -2,6 +2,9 @@ from cryptography.hazmat.primitives import serialization | ||||
| from cryptography.hazmat.primitives.asymmetric.ed25519 import Ed25519PrivateKey, Ed25519PublicKey | ||||
| from cryptography.hazmat.primitives.asymmetric.x25519 import X25519PrivateKey, X25519PublicKey | ||||
| 
 | ||||
| # These proxy classes exist to create a uniform API accross | ||||
| # cryptography primitive providers. | ||||
| 
 | ||||
| class X25519PrivateKeyProxy: | ||||
|     def __init__(self, real): | ||||
|         self.real = real | ||||
| @ -40,4 +43,48 @@ class X25519PublicKeyProxy: | ||||
|         return self.real.public_bytes( | ||||
|             encoding=serialization.Encoding.Raw, | ||||
|             format=serialization.PublicFormat.Raw | ||||
|         ) | ||||
|         ) | ||||
| 
 | ||||
| 
 | ||||
| class Ed25519PrivateKeyProxy: | ||||
|     def __init__(self, real): | ||||
|         self.real = real | ||||
| 
 | ||||
|     @classmethod | ||||
|     def generate(cls): | ||||
|         return cls(Ed25519PrivateKey.generate()) | ||||
| 
 | ||||
|     @classmethod | ||||
|     def from_private_bytes(cls, data): | ||||
|         return cls(Ed25519PrivateKey.from_private_bytes(data)) | ||||
| 
 | ||||
|     def private_bytes(self): | ||||
|         return self.real.private_bytes( | ||||
|             encoding=serialization.Encoding.Raw, | ||||
|             format=serialization.PrivateFormat.Raw, | ||||
|             encryption_algorithm=serialization.NoEncryption() | ||||
|         ) | ||||
| 
 | ||||
|     def public_key(self): | ||||
|         return Ed25519PublicKeyProxy(self.real.public_key()) | ||||
| 
 | ||||
|     def sign(self, message): | ||||
|         return self.real.sign(message) | ||||
| 
 | ||||
| 
 | ||||
| class Ed25519PublicKeyProxy: | ||||
|     def __init__(self, real): | ||||
|         self.real = real | ||||
| 
 | ||||
|     @classmethod | ||||
|     def from_public_bytes(cls, data): | ||||
|         return cls(Ed25519PublicKey.from_public_bytes(data)) | ||||
| 
 | ||||
|     def public_bytes(self): | ||||
|         return self.real.public_bytes( | ||||
|             encoding=serialization.Encoding.Raw, | ||||
|             format=serialization.PublicFormat.Raw | ||||
|         ) | ||||
| 
 | ||||
|     def verify(self, signature, message): | ||||
|         self.real.verify(signature, message) | ||||
| @ -10,13 +10,13 @@ import RNS.Cryptography.Provider as cp | ||||
| 
 | ||||
| if cp.PROVIDER == cp.PROVIDER_INTERNAL: | ||||
|     from RNS.Cryptography.X25519 import X25519PrivateKey, X25519PublicKey | ||||
| 
 | ||||
|     # TODO: Use internal Ed25519 | ||||
|     from cryptography.hazmat.primitives.asymmetric.ed25519 import Ed25519PrivateKey, Ed25519PublicKey | ||||
|     from RNS.Cryptography.Ed25519 import Ed25519PrivateKey, Ed25519PublicKey | ||||
| 
 | ||||
| elif cp.PROVIDER == cp.PROVIDER_PYCA: | ||||
|     from RNS.Cryptography.Proxies import X25519PrivateKeyProxy as X25519PrivateKey | ||||
|     from RNS.Cryptography.Proxies import X25519PublicKeyProxy as X25519PublicKey | ||||
|     from RNS.Cryptography.Proxies import Ed25519PrivateKeyProxy as Ed25519PrivateKey | ||||
|     from RNS.Cryptography.Proxies import Ed25519PublicKeyProxy as Ed25519PublicKey | ||||
| 
 | ||||
| modules = glob.glob(os.path.dirname(__file__)+"/*.py") | ||||
| __all__ = [ os.path.basename(f)[:-3] for f in modules if not f.endswith('__init__.py')] | ||||
|  | ||||
							
								
								
									
										0
									
								
								RNS/Cryptography/pure25519/__init__.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										0
									
								
								RNS/Cryptography/pure25519/__init__.py
									
									
									
									
									
										Normal file
									
								
							
							
								
								
									
										58
									
								
								RNS/Cryptography/pure25519/_ed25519.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										58
									
								
								RNS/Cryptography/pure25519/_ed25519.py
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,58 @@ | ||||
| # MIT License | ||||
| # | ||||
| # Copyright (c) 2015 Brian Warner and other contributors | ||||
| 
 | ||||
| # Permission is hereby granted, free of charge, to any person obtaining a copy | ||||
| # of this software and associated documentation files (the "Software"), to deal | ||||
| # in the Software without restriction, including without limitation the rights | ||||
| # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | ||||
| # copies of the Software, and to permit persons to whom the Software is | ||||
| # furnished to do so, subject to the following conditions: | ||||
| # | ||||
| # The above copyright notice and this permission notice shall be included in all | ||||
| # copies or substantial portions of the Software. | ||||
| # | ||||
| # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||||
| # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||||
| # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | ||||
| # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||||
| # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | ||||
| # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE | ||||
| # SOFTWARE. | ||||
| 
 | ||||
| from . import eddsa | ||||
| 
 | ||||
| class BadSignatureError(Exception): | ||||
|     pass | ||||
| 
 | ||||
| SECRETKEYBYTES = 64 | ||||
| PUBLICKEYBYTES = 32 | ||||
| SIGNATUREKEYBYTES = 64 | ||||
| 
 | ||||
| def publickey(seed32): | ||||
|     assert len(seed32) == 32 | ||||
|     vk32 = eddsa.publickey(seed32) | ||||
|     return vk32, seed32+vk32 | ||||
| 
 | ||||
| def sign(msg, skvk): | ||||
|     assert len(skvk) == 64 | ||||
|     sk = skvk[:32] | ||||
|     vk = skvk[32:] | ||||
|     sig = eddsa.signature(msg, sk, vk) | ||||
|     return sig+msg | ||||
| 
 | ||||
| def open(sigmsg, vk): | ||||
|     assert len(vk) == 32 | ||||
|     sig = sigmsg[:64] | ||||
|     msg = sigmsg[64:] | ||||
|     try: | ||||
|         valid = eddsa.checkvalid(sig, msg, vk) | ||||
|     except ValueError as e: | ||||
|         raise BadSignatureError(e) | ||||
|     except Exception as e: | ||||
|         if str(e) == "decoding point that is not on curve": | ||||
|             raise BadSignatureError(e) | ||||
|         raise | ||||
|     if not valid: | ||||
|         raise BadSignatureError() | ||||
|     return msg | ||||
							
								
								
									
										368
									
								
								RNS/Cryptography/pure25519/basic.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										368
									
								
								RNS/Cryptography/pure25519/basic.py
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,368 @@ | ||||
| # MIT License | ||||
| # | ||||
| # Copyright (c) 2015 Brian Warner and other contributors | ||||
| 
 | ||||
| # Permission is hereby granted, free of charge, to any person obtaining a copy | ||||
| # of this software and associated documentation files (the "Software"), to deal | ||||
| # in the Software without restriction, including without limitation the rights | ||||
| # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | ||||
| # copies of the Software, and to permit persons to whom the Software is | ||||
| # furnished to do so, subject to the following conditions: | ||||
| # | ||||
| # The above copyright notice and this permission notice shall be included in all | ||||
| # copies or substantial portions of the Software. | ||||
| # | ||||
| # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||||
| # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||||
| # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | ||||
| # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||||
| # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | ||||
| # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE | ||||
| # SOFTWARE. | ||||
| 
 | ||||
| import binascii, hashlib, itertools | ||||
| 
 | ||||
| Q = 2**255 - 19 | ||||
| L = 2**252 + 27742317777372353535851937790883648493 | ||||
| 
 | ||||
| def inv(x): | ||||
|     return pow(x, Q-2, Q) | ||||
| 
 | ||||
| d = -121665 * inv(121666) | ||||
| I = pow(2,(Q-1)//4,Q) | ||||
| 
 | ||||
| def xrecover(y): | ||||
|     xx = (y*y-1) * inv(d*y*y+1) | ||||
|     x = pow(xx,(Q+3)//8,Q) | ||||
|     if (x*x - xx) % Q != 0: x = (x*I) % Q | ||||
|     if x % 2 != 0: x = Q-x | ||||
|     return x | ||||
| 
 | ||||
| By = 4 * inv(5) | ||||
| Bx = xrecover(By) | ||||
| B = [Bx % Q,By % Q] | ||||
| 
 | ||||
| # Extended Coordinates: x=X/Z, y=Y/Z, x*y=T/Z | ||||
| # http://www.hyperelliptic.org/EFD/g1p/auto-twisted-extended-1.html | ||||
| 
 | ||||
| def xform_affine_to_extended(pt): | ||||
|     (x, y) = pt | ||||
|     return (x%Q, y%Q, 1, (x*y)%Q) # (X,Y,Z,T) | ||||
| 
 | ||||
| def xform_extended_to_affine(pt): | ||||
|     (x, y, z, _) = pt | ||||
|     return ((x*inv(z))%Q, (y*inv(z))%Q) | ||||
| 
 | ||||
| def double_element(pt): # extended->extended | ||||
|     # dbl-2008-hwcd | ||||
|     (X1, Y1, Z1, _) = pt | ||||
|     A = (X1*X1) | ||||
|     B = (Y1*Y1) | ||||
|     C = (2*Z1*Z1) | ||||
|     D = (-A) % Q | ||||
|     J = (X1+Y1) % Q | ||||
|     E = (J*J-A-B) % Q | ||||
|     G = (D+B) % Q | ||||
|     F = (G-C) % Q | ||||
|     H = (D-B) % Q | ||||
|     X3 = (E*F) % Q | ||||
|     Y3 = (G*H) % Q | ||||
|     Z3 = (F*G) % Q | ||||
|     T3 = (E*H) % Q | ||||
|     return (X3, Y3, Z3, T3) | ||||
| 
 | ||||
| def add_elements(pt1, pt2): # extended->extended | ||||
|     # add-2008-hwcd-3 . Slightly slower than add-2008-hwcd-4, but -3 is | ||||
|     # unified, so it's safe for general-purpose addition | ||||
|     (X1, Y1, Z1, T1) = pt1 | ||||
|     (X2, Y2, Z2, T2) = pt2 | ||||
|     A = ((Y1-X1)*(Y2-X2)) % Q | ||||
|     B = ((Y1+X1)*(Y2+X2)) % Q | ||||
|     C = T1*(2*d)*T2 % Q | ||||
|     D = Z1*2*Z2 % Q | ||||
|     E = (B-A) % Q | ||||
|     F = (D-C) % Q | ||||
|     G = (D+C) % Q | ||||
|     H = (B+A) % Q | ||||
|     X3 = (E*F) % Q | ||||
|     Y3 = (G*H) % Q | ||||
|     T3 = (E*H) % Q | ||||
|     Z3 = (F*G) % Q | ||||
|     return (X3, Y3, Z3, T3) | ||||
| 
 | ||||
| def scalarmult_element_safe_slow(pt, n): | ||||
|     # this form is slightly slower, but tolerates arbitrary points, including | ||||
|     # those which are not in the main 1*L subgroup. This includes points of | ||||
|     # order 1 (the neutral element Zero), 2, 4, and 8. | ||||
|     assert n >= 0 | ||||
|     if n==0: | ||||
|         return xform_affine_to_extended((0,1)) | ||||
|     _ = double_element(scalarmult_element_safe_slow(pt, n>>1)) | ||||
|     return add_elements(_, pt) if n&1 else _ | ||||
| 
 | ||||
| def _add_elements_nonunfied(pt1, pt2): # extended->extended | ||||
|     # add-2008-hwcd-4 : NOT unified, only for pt1!=pt2. About 10% faster than | ||||
|     # the (unified) add-2008-hwcd-3, and safe to use inside scalarmult if you | ||||
|     # aren't using points of order 1/2/4/8 | ||||
|     (X1, Y1, Z1, T1) = pt1 | ||||
|     (X2, Y2, Z2, T2) = pt2 | ||||
|     A = ((Y1-X1)*(Y2+X2)) % Q | ||||
|     B = ((Y1+X1)*(Y2-X2)) % Q | ||||
|     C = (Z1*2*T2) % Q | ||||
|     D = (T1*2*Z2) % Q | ||||
|     E = (D+C) % Q | ||||
|     F = (B-A) % Q | ||||
|     G = (B+A) % Q | ||||
|     H = (D-C) % Q | ||||
|     X3 = (E*F) % Q | ||||
|     Y3 = (G*H) % Q | ||||
|     Z3 = (F*G) % Q | ||||
|     T3 = (E*H) % Q | ||||
|     return (X3, Y3, Z3, T3) | ||||
| 
 | ||||
| def scalarmult_element(pt, n): # extended->extended | ||||
|     # This form only works properly when given points that are a member of | ||||
|     # the main 1*L subgroup. It will give incorrect answers when called with | ||||
|     # the points of order 1/2/4/8, including point Zero. (it will also work | ||||
|     # properly when given points of order 2*L/4*L/8*L) | ||||
|     assert n >= 0 | ||||
|     if n==0: | ||||
|         return xform_affine_to_extended((0,1)) | ||||
|     _ = double_element(scalarmult_element(pt, n>>1)) | ||||
|     return _add_elements_nonunfied(_, pt) if n&1 else _ | ||||
| 
 | ||||
| # points are encoded as 32-bytes little-endian, b255 is sign, b2b1b0 are 0 | ||||
| 
 | ||||
| def encodepoint(P): | ||||
|     x = P[0] | ||||
|     y = P[1] | ||||
|     # MSB of output equals x.b0 (=x&1) | ||||
|     # rest of output is little-endian y | ||||
|     assert 0 <= y < (1<<255) # always < 0x7fff..ff | ||||
|     if x & 1: | ||||
|         y += 1<<255 | ||||
|     return binascii.unhexlify("%064x" % y)[::-1] | ||||
| 
 | ||||
| def isoncurve(P): | ||||
|     x = P[0] | ||||
|     y = P[1] | ||||
|     return (-x*x + y*y - 1 - d*x*x*y*y) % Q == 0 | ||||
| 
 | ||||
| class NotOnCurve(Exception): | ||||
|     pass | ||||
| 
 | ||||
| def decodepoint(s): | ||||
|     unclamped = int(binascii.hexlify(s[:32][::-1]), 16) | ||||
|     clamp = (1 << 255) - 1 | ||||
|     y = unclamped & clamp # clear MSB | ||||
|     x = xrecover(y) | ||||
|     if bool(x & 1) != bool(unclamped & (1<<255)): x = Q-x | ||||
|     P = [x,y] | ||||
|     if not isoncurve(P): raise NotOnCurve("decoding point that is not on curve") | ||||
|     return P | ||||
| 
 | ||||
| # scalars are encoded as 32-bytes little-endian | ||||
| 
 | ||||
| def bytes_to_scalar(s): | ||||
|     assert len(s) == 32, len(s) | ||||
|     return int(binascii.hexlify(s[::-1]), 16) | ||||
| 
 | ||||
| def bytes_to_clamped_scalar(s): | ||||
|     # Ed25519 private keys clamp the scalar to ensure two things: | ||||
|     #   1: integer value is in L/2 .. L, to avoid small-logarithm | ||||
|     #      non-wraparaound | ||||
|     #   2: low-order 3 bits are zero, so a small-subgroup attack won't learn | ||||
|     #      any information | ||||
|     # set the top two bits to 01, and the bottom three to 000 | ||||
|     a_unclamped = bytes_to_scalar(s) | ||||
|     AND_CLAMP = (1<<254) - 1 - 7 | ||||
|     OR_CLAMP = (1<<254) | ||||
|     a_clamped = (a_unclamped & AND_CLAMP) | OR_CLAMP | ||||
|     return a_clamped | ||||
| 
 | ||||
| def random_scalar(entropy_f): # 0..L-1 inclusive | ||||
|     # reduce the bias to a safe level by generating 256 extra bits | ||||
|     oversized = int(binascii.hexlify(entropy_f(32+32)), 16) | ||||
|     return oversized % L | ||||
| 
 | ||||
| def password_to_scalar(pw): | ||||
|     oversized = hashlib.sha512(pw).digest() | ||||
|     return int(binascii.hexlify(oversized), 16) % L | ||||
| 
 | ||||
| def scalar_to_bytes(y): | ||||
|     y = y % L | ||||
|     assert 0 <= y < 2**256 | ||||
|     return binascii.unhexlify("%064x" % y)[::-1] | ||||
| 
 | ||||
| # Elements, of various orders | ||||
| 
 | ||||
| def is_extended_zero(XYTZ): | ||||
|     # catch Zero | ||||
|     (X, Y, Z, T) = XYTZ | ||||
|     Y = Y % Q | ||||
|     Z = Z % Q | ||||
|     if X==0 and Y==Z and Y!=0: | ||||
|         return True | ||||
|     return False | ||||
| 
 | ||||
| class ElementOfUnknownGroup: | ||||
|     # This is used for points of order 2,4,8,2*L,4*L,8*L | ||||
|     def __init__(self, XYTZ): | ||||
|         assert isinstance(XYTZ, tuple) | ||||
|         assert len(XYTZ) == 4 | ||||
|         self.XYTZ = XYTZ | ||||
| 
 | ||||
|     def add(self, other): | ||||
|         if not isinstance(other, ElementOfUnknownGroup): | ||||
|             raise TypeError("elements can only be added to other elements") | ||||
|         sum_XYTZ = add_elements(self.XYTZ, other.XYTZ) | ||||
|         if is_extended_zero(sum_XYTZ): | ||||
|             return Zero | ||||
|         return ElementOfUnknownGroup(sum_XYTZ) | ||||
| 
 | ||||
|     def scalarmult(self, s): | ||||
|         if isinstance(s, ElementOfUnknownGroup): | ||||
|             raise TypeError("elements cannot be multiplied together") | ||||
|         assert s >= 0 | ||||
|         product = scalarmult_element_safe_slow(self.XYTZ, s) | ||||
|         return ElementOfUnknownGroup(product) | ||||
| 
 | ||||
|     def to_bytes(self): | ||||
|         return encodepoint(xform_extended_to_affine(self.XYTZ)) | ||||
|     def __eq__(self, other): | ||||
|         return self.to_bytes() == other.to_bytes() | ||||
|     def __ne__(self, other): | ||||
|         return not self == other | ||||
| 
 | ||||
| class Element(ElementOfUnknownGroup): | ||||
|     # this only holds elements in the main 1*L subgroup. It never holds Zero, | ||||
|     # or elements of order 1/2/4/8, or 2*L/4*L/8*L. | ||||
| 
 | ||||
|     def add(self, other): | ||||
|         if not isinstance(other, ElementOfUnknownGroup): | ||||
|             raise TypeError("elements can only be added to other elements") | ||||
|         sum_element = ElementOfUnknownGroup.add(self, other) | ||||
|         if sum_element is Zero: | ||||
|             return sum_element | ||||
|         if isinstance(other, Element): | ||||
|             # adding two subgroup elements results in another subgroup | ||||
|             # element, or Zero, and we've already excluded Zero | ||||
|             return Element(sum_element.XYTZ) | ||||
|         # not necessarily a subgroup member, so assume not | ||||
|         return sum_element | ||||
| 
 | ||||
|     def scalarmult(self, s): | ||||
|         if isinstance(s, ElementOfUnknownGroup): | ||||
|             raise TypeError("elements cannot be multiplied together") | ||||
|         # scalarmult of subgroup members can be done modulo the subgroup | ||||
|         # order, and using the faster non-unified function. | ||||
|         s = s % L | ||||
|         # scalarmult(s=0) gets you Zero | ||||
|         if s == 0: | ||||
|             return Zero | ||||
|         # scalarmult(s=1) gets you self, which is a subgroup member | ||||
|         # scalarmult(s<grouporder) gets you a different subgroup member | ||||
|         return Element(scalarmult_element(self.XYTZ, s)) | ||||
| 
 | ||||
|     # negation and subtraction only make sense for the main subgroup | ||||
|     def negate(self): | ||||
|         # slow. Prefer e.scalarmult(-pw) to e.scalarmult(pw).negate() | ||||
|         return Element(scalarmult_element(self.XYTZ, L-2)) | ||||
|     def subtract(self, other): | ||||
|         return self.add(other.negate()) | ||||
| 
 | ||||
| class _ZeroElement(ElementOfUnknownGroup): | ||||
|     def add(self, other): | ||||
|         return other # zero+anything = anything | ||||
|     def scalarmult(self, s): | ||||
|         return self # zero*anything = zero | ||||
|     def negate(self): | ||||
|         return self # -zero = zero | ||||
|     def subtract(self, other): | ||||
|         return self.add(other.negate()) | ||||
| 
 | ||||
| 
 | ||||
| Base = Element(xform_affine_to_extended(B)) | ||||
| Zero = _ZeroElement(xform_affine_to_extended((0,1))) # the neutral (identity) element | ||||
| 
 | ||||
| _zero_bytes = Zero.to_bytes() | ||||
| 
 | ||||
| 
 | ||||
| def arbitrary_element(seed): # unknown DL | ||||
|     # TODO: if we don't need uniformity, maybe use just sha256 here? | ||||
|     hseed = hashlib.sha512(seed).digest() | ||||
|     y = int(binascii.hexlify(hseed), 16) % Q | ||||
| 
 | ||||
|     # we try successive Y values until we find a valid point | ||||
|     for plus in itertools.count(0): | ||||
|         y_plus = (y + plus) % Q | ||||
|         x = xrecover(y_plus) | ||||
|         Pa = [x,y_plus] # no attempt to use both "positive" and "negative" X | ||||
| 
 | ||||
|         # only about 50% of Y coordinates map to valid curve points (I think | ||||
|         # the other half give you points on the "twist"). | ||||
|         if not isoncurve(Pa): | ||||
|             continue | ||||
| 
 | ||||
|         P = ElementOfUnknownGroup(xform_affine_to_extended(Pa)) | ||||
|         # even if the point is on our curve, it may not be in our particular | ||||
|         # (order=L) subgroup. The curve has order 8*L, so an arbitrary point | ||||
|         # could have order 1,2,4,8,1*L,2*L,4*L,8*L (everything which divides | ||||
|         # the group order). | ||||
| 
 | ||||
|         # [I MAY BE COMPLETELY WRONG ABOUT THIS, but my brief statistical | ||||
|         # tests suggest it's not too far off] There are phi(x) points with | ||||
|         # order x, so: | ||||
|         #  1 element of order 1: [(x=0,y=1)=Zero] | ||||
|         #  1 element of order 2 [(x=0,y=-1)] | ||||
|         #  2 elements of order 4 | ||||
|         #  4 elements of order 8 | ||||
|         #  L-1 elements of order L (including Base) | ||||
|         #  L-1 elements of order 2*L | ||||
|         #  2*(L-1) elements of order 4*L | ||||
|         #  4*(L-1) elements of order 8*L | ||||
| 
 | ||||
|         # So 50% of random points will have order 8*L, 25% will have order | ||||
|         # 4*L, 13% order 2*L, and 13% will have our desired order 1*L (and a | ||||
|         # vanishingly small fraction will have 1/2/4/8). If we multiply any | ||||
|         # of the 8*L points by 2, we're sure to get an 4*L point (and | ||||
|         # multiplying a 4*L point by 2 gives us a 2*L point, and so on). | ||||
|         # Multiplying a 1*L point by 2 gives us a different 1*L point. So | ||||
|         # multiplying by 8 gets us from almost any point into a uniform point | ||||
|         # on the correct 1*L subgroup. | ||||
| 
 | ||||
|         P8 = P.scalarmult(8) | ||||
| 
 | ||||
|         # if we got really unlucky and picked one of the 8 low-order points, | ||||
|         # multiplying by 8 will get us to the identity (Zero), which we check | ||||
|         # for explicitly. | ||||
|         if is_extended_zero(P8.XYTZ): | ||||
|             continue | ||||
| 
 | ||||
|         # Test that we're finally in the right group. We want to scalarmult | ||||
|         # by L, and we want to *not* use the trick in Group.scalarmult() | ||||
|         # which does x%L, because that would bypass the check we care about. | ||||
|         # P is still an _ElementOfUnknownGroup, which doesn't use x%L because | ||||
|         # that's not correct for points outside the main group. | ||||
|         assert is_extended_zero(P8.scalarmult(L).XYTZ) | ||||
| 
 | ||||
|         return Element(P8.XYTZ) | ||||
|     # never reached | ||||
| 
 | ||||
| def bytes_to_unknown_group_element(bytes): | ||||
|     # this accepts all elements, including Zero and wrong-subgroup ones | ||||
|     if bytes == _zero_bytes: | ||||
|         return Zero | ||||
|     XYTZ = xform_affine_to_extended(decodepoint(bytes)) | ||||
|     return ElementOfUnknownGroup(XYTZ) | ||||
| 
 | ||||
| def bytes_to_element(bytes): | ||||
|     # this strictly only accepts elements in the right subgroup | ||||
|     P = bytes_to_unknown_group_element(bytes) | ||||
|     if P is Zero: | ||||
|         raise ValueError("element was Zero") | ||||
|     if not is_extended_zero(P.scalarmult(L).XYTZ): | ||||
|         raise ValueError("element is not in the right group") | ||||
|     # the point is in the expected 1*L subgroup, not in the 2/4/8 groups, | ||||
|     # or in the 2*L/4*L/8*L groups. Promote it to a correct-group Element. | ||||
|     return Element(P.XYTZ) | ||||
							
								
								
									
										213
									
								
								RNS/Cryptography/pure25519/ed25519_oop.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										213
									
								
								RNS/Cryptography/pure25519/ed25519_oop.py
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,213 @@ | ||||
| # MIT License | ||||
| # | ||||
| # Copyright (c) 2015 Brian Warner and other contributors | ||||
| 
 | ||||
| # Permission is hereby granted, free of charge, to any person obtaining a copy | ||||
| # of this software and associated documentation files (the "Software"), to deal | ||||
| # in the Software without restriction, including without limitation the rights | ||||
| # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | ||||
| # copies of the Software, and to permit persons to whom the Software is | ||||
| # furnished to do so, subject to the following conditions: | ||||
| # | ||||
| # The above copyright notice and this permission notice shall be included in all | ||||
| # copies or substantial portions of the Software. | ||||
| # | ||||
| # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||||
| # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||||
| # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | ||||
| # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||||
| # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | ||||
| # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE | ||||
| # SOFTWARE. | ||||
| 
 | ||||
| import os | ||||
| import base64 | ||||
| from . import _ed25519 | ||||
| BadSignatureError = _ed25519.BadSignatureError | ||||
| 
 | ||||
| def create_keypair(entropy=os.urandom): | ||||
|     SEEDLEN = int(_ed25519.SECRETKEYBYTES/2) | ||||
|     assert SEEDLEN == 32 | ||||
|     seed = entropy(SEEDLEN) | ||||
|     sk = SigningKey(seed) | ||||
|     vk = sk.get_verifying_key() | ||||
|     return sk, vk | ||||
| 
 | ||||
| class BadPrefixError(Exception): | ||||
|     pass | ||||
| 
 | ||||
| def remove_prefix(s_bytes, prefix): | ||||
|     assert(type(s_bytes) == type(prefix)) | ||||
|     if s_bytes[:len(prefix)] != prefix: | ||||
|         raise BadPrefixError("did not see expected '%s' prefix" % (prefix,)) | ||||
|     return s_bytes[len(prefix):] | ||||
| 
 | ||||
| def to_ascii(s_bytes, prefix="", encoding="base64"): | ||||
|     """Return a version-prefixed ASCII representation of the given binary | ||||
|     string. 'encoding' indicates how to do the encoding, and can be one of: | ||||
|      * base64 | ||||
|      * base32 | ||||
|      * base16 (or hex) | ||||
| 
 | ||||
|     This function handles bytes, not bits, so it does not append any trailing | ||||
|     '=' (unlike standard base64.b64encode). It also lowercases the base32 | ||||
|     output. | ||||
| 
 | ||||
|     'prefix' will be prepended to the encoded form, and is useful for | ||||
|     distinguishing the purpose and version of the binary string. E.g. you | ||||
|     could prepend 'pub0-' to a VerifyingKey string to allow the receiving | ||||
|     code to raise a useful error if someone pasted in a signature string by | ||||
|     mistake. | ||||
|     """ | ||||
|     assert isinstance(s_bytes, bytes) | ||||
|     if not isinstance(prefix, bytes): | ||||
|         prefix = prefix.encode('ascii') | ||||
|     if encoding == "base64": | ||||
|         s_ascii = base64.b64encode(s_bytes).decode('ascii').rstrip("=") | ||||
|     elif encoding == "base32": | ||||
|         s_ascii = base64.b32encode(s_bytes).decode('ascii').rstrip("=").lower() | ||||
|     elif encoding in ("base16", "hex"): | ||||
|         s_ascii = base64.b16encode(s_bytes).decode('ascii').lower() | ||||
|     else: | ||||
|         raise NotImplementedError | ||||
|     return prefix+s_ascii.encode('ascii') | ||||
| 
 | ||||
| def from_ascii(s_ascii, prefix="", encoding="base64"): | ||||
|     """This is the opposite of to_ascii. It will throw BadPrefixError if | ||||
|     the prefix is not found. | ||||
|     """ | ||||
|     if isinstance(s_ascii, bytes): | ||||
|         s_ascii = s_ascii.decode('ascii') | ||||
|     if isinstance(prefix, bytes): | ||||
|         prefix = prefix.decode('ascii') | ||||
|     s_ascii = remove_prefix(s_ascii.strip(), prefix) | ||||
|     if encoding == "base64": | ||||
|         s_ascii += "="*((4 - len(s_ascii)%4)%4) | ||||
|         s_bytes = base64.b64decode(s_ascii) | ||||
|     elif encoding == "base32": | ||||
|         s_ascii += "="*((8 - len(s_ascii)%8)%8) | ||||
|         s_bytes = base64.b32decode(s_ascii.upper()) | ||||
|     elif encoding in ("base16", "hex"): | ||||
|         s_bytes = base64.b16decode(s_ascii.upper()) | ||||
|     else: | ||||
|         raise NotImplementedError | ||||
|     return s_bytes | ||||
| 
 | ||||
| class SigningKey(object): | ||||
|     # this can only be used to reconstruct a key created by create_keypair(). | ||||
|     def __init__(self, sk_s, prefix="", encoding=None): | ||||
|         assert isinstance(sk_s, bytes) | ||||
|         if not isinstance(prefix, bytes): | ||||
|             prefix = prefix.encode('ascii') | ||||
|         sk_s = remove_prefix(sk_s, prefix) | ||||
|         if encoding is not None: | ||||
|             sk_s = from_ascii(sk_s, encoding=encoding) | ||||
|         if len(sk_s) == 32: | ||||
|             # create from seed | ||||
|             vk_s, sk_s = _ed25519.publickey(sk_s) | ||||
|         else: | ||||
|             if len(sk_s) != 32+32: | ||||
|                 raise ValueError("SigningKey takes 32-byte seed or 64-byte string") | ||||
|         self.sk_s = sk_s # seed+pubkey | ||||
|         self.vk_s = sk_s[32:] # just pubkey | ||||
| 
 | ||||
|     def to_bytes(self, prefix=""): | ||||
|         if not isinstance(prefix, bytes): | ||||
|             prefix = prefix.encode('ascii') | ||||
|         return prefix+self.sk_s | ||||
| 
 | ||||
|     def to_ascii(self, prefix="", encoding=None): | ||||
|         assert encoding | ||||
|         if not isinstance(prefix, bytes): | ||||
|             prefix = prefix.encode('ascii') | ||||
|         return to_ascii(self.to_seed(), prefix, encoding) | ||||
| 
 | ||||
|     def to_seed(self, prefix=""): | ||||
|         if not isinstance(prefix, bytes): | ||||
|             prefix = prefix.encode('ascii') | ||||
|         return prefix+self.sk_s[:32] | ||||
| 
 | ||||
|     def __eq__(self, them): | ||||
|         if not isinstance(them, object): return False | ||||
|         return (them.__class__ == self.__class__ | ||||
|                 and them.sk_s == self.sk_s) | ||||
| 
 | ||||
|     def get_verifying_key(self): | ||||
|         return VerifyingKey(self.vk_s) | ||||
| 
 | ||||
|     def sign(self, msg, prefix="", encoding=None): | ||||
|         assert isinstance(msg, bytes) | ||||
|         if not isinstance(prefix, bytes): | ||||
|             prefix = prefix.encode('ascii') | ||||
|         sig_and_msg = _ed25519.sign(msg, self.sk_s) | ||||
|         # the response is R+S+msg | ||||
|         sig_R = sig_and_msg[0:32] | ||||
|         sig_S = sig_and_msg[32:64] | ||||
|         msg_out = sig_and_msg[64:] | ||||
|         sig_out = sig_R + sig_S | ||||
|         assert msg_out == msg | ||||
|         if encoding: | ||||
|             return to_ascii(sig_out, prefix, encoding) | ||||
|         return prefix+sig_out | ||||
| 
 | ||||
| class VerifyingKey(object): | ||||
|     def __init__(self, vk_s, prefix="", encoding=None): | ||||
|         if not isinstance(prefix, bytes): | ||||
|             prefix = prefix.encode('ascii') | ||||
|         if not isinstance(vk_s, bytes): | ||||
|             vk_s = vk_s.encode('ascii') | ||||
|         assert isinstance(vk_s, bytes) | ||||
|         vk_s = remove_prefix(vk_s, prefix) | ||||
|         if encoding is not None: | ||||
|             vk_s = from_ascii(vk_s, encoding=encoding) | ||||
| 
 | ||||
|         assert len(vk_s) == 32 | ||||
|         self.vk_s = vk_s | ||||
| 
 | ||||
|     def to_bytes(self, prefix=""): | ||||
|         if not isinstance(prefix, bytes): | ||||
|             prefix = prefix.encode('ascii') | ||||
|         return prefix+self.vk_s | ||||
| 
 | ||||
|     def to_ascii(self, prefix="", encoding=None): | ||||
|         assert encoding | ||||
|         if not isinstance(prefix, bytes): | ||||
|             prefix = prefix.encode('ascii') | ||||
|         return to_ascii(self.vk_s, prefix, encoding) | ||||
| 
 | ||||
|     def __eq__(self, them): | ||||
|         if not isinstance(them, object): return False | ||||
|         return (them.__class__ == self.__class__ | ||||
|                 and them.vk_s == self.vk_s) | ||||
| 
 | ||||
|     def verify(self, sig, msg, prefix="", encoding=None): | ||||
|         if not isinstance(sig, bytes): | ||||
|             sig = sig.encode('ascii') | ||||
|         if not isinstance(prefix, bytes): | ||||
|             prefix = prefix.encode('ascii') | ||||
|         assert isinstance(sig, bytes) | ||||
|         assert isinstance(msg, bytes) | ||||
|         if encoding: | ||||
|             sig = from_ascii(sig, prefix, encoding) | ||||
|         else: | ||||
|             sig = remove_prefix(sig, prefix) | ||||
|         assert len(sig) == 64 | ||||
|         sig_R = sig[:32] | ||||
|         sig_S = sig[32:] | ||||
|         sig_and_msg = sig_R + sig_S + msg | ||||
|         # this might raise BadSignatureError | ||||
|         msg2 = _ed25519.open(sig_and_msg, self.vk_s) | ||||
|         assert msg2 == msg | ||||
| 
 | ||||
| def selftest(): | ||||
|     message = b"crypto libraries should always test themselves at powerup" | ||||
|     sk = SigningKey(b"priv0-VIsfn5OFGa09Un2MR6Hm7BQ5++xhcQskU2OGXG8jSJl4cWLZrRrVcSN2gVYMGtZT+3354J5jfmqAcuRSD9KIyg", | ||||
|                     prefix="priv0-", encoding="base64") | ||||
|     vk = VerifyingKey(b"pub0-eHFi2a0a1XEjdoFWDBrWU/t9+eCeY35qgHLkUg/SiMo", | ||||
|                       prefix="pub0-", encoding="base64") | ||||
|     assert sk.get_verifying_key() == vk | ||||
|     sig = sk.sign(message, prefix="sig0-", encoding="base64") | ||||
|     assert sig == b"sig0-E/QrwtSF52x8+q0l4ahA7eJbRKc777ClKNg217Q0z4fiYMCdmAOI+rTLVkiFhX6k3D+wQQfKdJYMxaTUFfv1DQ", sig | ||||
|     vk.verify(sig, message, prefix="sig0-", encoding="base64") | ||||
| 
 | ||||
| selftest() | ||||
							
								
								
									
										94
									
								
								RNS/Cryptography/pure25519/eddsa.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										94
									
								
								RNS/Cryptography/pure25519/eddsa.py
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,94 @@ | ||||
| # MIT License | ||||
| # | ||||
| # Copyright (c) 2015 Brian Warner and other contributors | ||||
| 
 | ||||
| # Permission is hereby granted, free of charge, to any person obtaining a copy | ||||
| # of this software and associated documentation files (the "Software"), to deal | ||||
| # in the Software without restriction, including without limitation the rights | ||||
| # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | ||||
| # copies of the Software, and to permit persons to whom the Software is | ||||
| # furnished to do so, subject to the following conditions: | ||||
| # | ||||
| # The above copyright notice and this permission notice shall be included in all | ||||
| # copies or substantial portions of the Software. | ||||
| # | ||||
| # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||||
| # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||||
| # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | ||||
| # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||||
| # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | ||||
| # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE | ||||
| # SOFTWARE. | ||||
| 
 | ||||
| from RNS.Cryptography.Hashes import sha512 | ||||
| from .basic import (bytes_to_clamped_scalar, | ||||
|                     bytes_to_scalar, scalar_to_bytes, | ||||
|                     bytes_to_element, Base) | ||||
| import hashlib, binascii | ||||
| 
 | ||||
| def H(m): | ||||
|     return sha512(m) | ||||
| 
 | ||||
| def publickey(seed): | ||||
|     # turn first half of SHA512(seed) into scalar, then into point | ||||
|     assert len(seed) == 32 | ||||
|     a = bytes_to_clamped_scalar(H(seed)[:32]) | ||||
|     A = Base.scalarmult(a) | ||||
|     return A.to_bytes() | ||||
| 
 | ||||
| def Hint(m): | ||||
|     h = H(m) | ||||
|     return int(binascii.hexlify(h[::-1]), 16) | ||||
| 
 | ||||
| def signature(m,sk,pk): | ||||
|     assert len(sk) == 32 # seed | ||||
|     assert len(pk) == 32 | ||||
|     h = H(sk[:32]) | ||||
|     a_bytes, inter = h[:32], h[32:] | ||||
|     a = bytes_to_clamped_scalar(a_bytes) | ||||
|     r = Hint(inter + m) | ||||
|     R = Base.scalarmult(r) | ||||
|     R_bytes = R.to_bytes() | ||||
|     S = r + Hint(R_bytes + pk + m) * a | ||||
|     return R_bytes + scalar_to_bytes(S) | ||||
| 
 | ||||
| def checkvalid(s, m, pk): | ||||
|     if len(s) != 64: raise Exception("signature length is wrong") | ||||
|     if len(pk) != 32: raise Exception("public-key length is wrong") | ||||
|     R = bytes_to_element(s[:32]) | ||||
|     A = bytes_to_element(pk) | ||||
|     S = bytes_to_scalar(s[32:]) | ||||
|     h = Hint(s[:32] + pk + m) | ||||
|     v1 = Base.scalarmult(S) | ||||
|     v2 = R.add(A.scalarmult(h)) | ||||
|     return v1==v2 | ||||
| 
 | ||||
| # wrappers | ||||
| 
 | ||||
| import os | ||||
| 
 | ||||
| def create_signing_key(): | ||||
|     seed = os.urandom(32) | ||||
|     return seed | ||||
| 
 | ||||
| def create_verifying_key(signing_key): | ||||
|     return publickey(signing_key) | ||||
| 
 | ||||
| def sign(skbytes, msg): | ||||
|     """Return just the signature, given the message and just the secret | ||||
|     key.""" | ||||
|     if len(skbytes) != 32: | ||||
|         raise ValueError("Bad signing key length %d" % len(skbytes)) | ||||
|     vkbytes = create_verifying_key(skbytes) | ||||
|     sig = signature(msg, skbytes, vkbytes) | ||||
|     return sig | ||||
| 
 | ||||
| def verify(vkbytes, sig, msg): | ||||
|     if len(vkbytes) != 32: | ||||
|         raise ValueError("Bad verifying key length %d" % len(vkbytes)) | ||||
|     if len(sig) != 64: | ||||
|         raise ValueError("Bad signature length %d" % len(sig)) | ||||
|     rc = checkvalid(sig, msg, vkbytes) | ||||
|     if not rc: | ||||
|         raise ValueError("rc != 0", rc) | ||||
|     return True | ||||
| @ -28,10 +28,8 @@ import atexit | ||||
| import hashlib | ||||
| 
 | ||||
| from .vendor import umsgpack as umsgpack | ||||
| from cryptography.hazmat.primitives import serialization | ||||
| from cryptography.hazmat.primitives.asymmetric.ed25519 import Ed25519PrivateKey, Ed25519PublicKey | ||||
| 
 | ||||
| from RNS.Cryptography import X25519PrivateKey, X25519PublicKey | ||||
| from RNS.Cryptography import X25519PrivateKey, X25519PublicKey, Ed25519PrivateKey, Ed25519PublicKey | ||||
| from RNS.Cryptography import Fernet | ||||
| 
 | ||||
| 
 | ||||
| @ -294,20 +292,13 @@ class Identity: | ||||
|         self.prv_bytes     = self.prv.private_bytes() | ||||
| 
 | ||||
|         self.sig_prv       = Ed25519PrivateKey.generate() | ||||
|         self.sig_prv_bytes = self.sig_prv.private_bytes( | ||||
|             encoding=serialization.Encoding.Raw, | ||||
|             format=serialization.PrivateFormat.Raw, | ||||
|             encryption_algorithm=serialization.NoEncryption() | ||||
|         ) | ||||
|         self.sig_prv_bytes = self.sig_prv.private_bytes() | ||||
| 
 | ||||
|         self.pub           = self.prv.public_key() | ||||
|         self.pub_bytes     = self.pub.public_bytes() | ||||
| 
 | ||||
|         self.sig_pub       = self.sig_prv.public_key() | ||||
|         self.sig_pub_bytes = self.sig_pub.public_bytes( | ||||
|             encoding=serialization.Encoding.Raw, | ||||
|             format=serialization.PublicFormat.Raw | ||||
|         ) | ||||
|         self.sig_pub_bytes = self.sig_pub.public_bytes() | ||||
| 
 | ||||
|         self.update_hashes() | ||||
| 
 | ||||
| @ -342,10 +333,7 @@ class Identity: | ||||
|             self.pub_bytes     = self.pub.public_bytes() | ||||
| 
 | ||||
|             self.sig_pub       = self.sig_prv.public_key() | ||||
|             self.sig_pub_bytes = self.sig_pub.public_bytes( | ||||
|                 encoding=serialization.Encoding.Raw, | ||||
|                 format=serialization.PublicFormat.Raw | ||||
|             ) | ||||
|             self.sig_pub_bytes = self.sig_pub.public_bytes() | ||||
| 
 | ||||
|             self.update_hashes() | ||||
| 
 | ||||
|  | ||||
							
								
								
									
										11
									
								
								RNS/Link.py
									
									
									
									
									
								
							
							
						
						
									
										11
									
								
								RNS/Link.py
									
									
									
									
									
								
							| @ -20,11 +20,7 @@ | ||||
| # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE | ||||
| # SOFTWARE. | ||||
| 
 | ||||
| from cryptography.hazmat.primitives import hashes | ||||
| from cryptography.hazmat.primitives import serialization | ||||
| from cryptography.hazmat.primitives.asymmetric.ed25519 import Ed25519PrivateKey, Ed25519PublicKey | ||||
| 
 | ||||
| from RNS.Cryptography import X25519PrivateKey, X25519PublicKey | ||||
| from RNS.Cryptography import X25519PrivateKey, X25519PublicKey, Ed25519PrivateKey, Ed25519PublicKey | ||||
| from RNS.Cryptography import Fernet | ||||
| 
 | ||||
| from time import sleep | ||||
| @ -180,10 +176,7 @@ class Link: | ||||
|         self.pub_bytes = self.pub.public_bytes() | ||||
| 
 | ||||
|         self.sig_pub = self.sig_prv.public_key() | ||||
|         self.sig_pub_bytes = self.sig_pub.public_bytes( | ||||
|             encoding=serialization.Encoding.Raw, | ||||
|             format=serialization.PublicFormat.Raw | ||||
|         ) | ||||
|         self.sig_pub_bytes = self.sig_pub.public_bytes() | ||||
| 
 | ||||
|         if peer_pub_bytes == None: | ||||
|             self.peer_pub = None | ||||
|  | ||||
| @ -1 +1 @@ | ||||
| __version__ = "0.3.7" | ||||
| __version__ = "0.3.8" | ||||
|  | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user