Source code for ecpy.eddsa

# Copyright 2016 Cedric Mesnil <cedric.mesnil@ubinity.com>, Ubinity SAS
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#     http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.


#python 2 compatibility
from builtins import int,pow


from ecpy.curves import Curve,Point
from ecpy.keys import ECPublicKey, ECPrivateKey
from ecpy.formatters import decode_sig, encode_sig
import hashlib

[docs]class EDDSA: """EDDSA signer implemenation according to: - IETF `draft-irtf-cfrg-eddsa-05 <https://tools.ietf.org/html/draft-irtf-cfrg-eddsa-05>`_. Args: hasher (hashlib): callable constructor returning an object with update(), digest() interface. Example: hashlib.sha256, hashlib.sha512... fmt (str): in/out signature format. See :mod:`ecpy.formatters`. """ def __init__(self, hasher, fmt="EDDSA"): self._hasher = hasher self.fmt = fmt pass
[docs] def sign(self, msg, pv_key): """ Signs a message. Args: msg (bytes) : the message to sign pv_key (ecpy.keys.ECPrivateKey): key to use for signing """ return self._do_sign(msg, pv_key)
def _do_sign(self,msg,pv_key): curve = pv_key.curve B = curve.generator n = curve.order size = curve.size >>3 k = pv_key.d.to_bytes(size,'big') hasher = self._hasher() hasher.update(k) h = hasher.digest() #retrieve encoded pub key a = bytearray(h[size-1::-1]) a[0] &= ~0x40; a[0] |= 0x40; a[31] &= 0xF8; a = bytes(a) a = int.from_bytes(a,'big') A = a * B eA = curve.encode_point(A) #OK #compute R hasher = self._hasher() hasher.update(h[size:]+msg) r = hasher.digest() r = int.from_bytes(r,'little') r = r % n R = r*B eR = curve.encode_point(R) #compute S hasher = self._hasher() hasher.update(eR+eA+msg) H_eR_eA_m = hasher.digest() i = int.from_bytes(H_eR_eA_m, 'little') S = (r + i*a)%n #S = S.to_bytes(size,'little') #return eR+S eR = int.from_bytes(eR,'little') sig = encode_sig(eR,S,self.fmt,size) return sig
[docs] def verify(self,msg,sig,pu_key): """ Verifies a message signature. Args: msg (bytes) : the message to verify the signature sig (bytes) : signature to verify pu_key (ecpy.keys.ECPublicKey): key to use for verifying """ curve = pu_key.curve n = curve.order size = curve.size>>3 #eR = sig[0:size] #S = int.from_bytes(sig[size:],'little') eR,S = decode_sig(sig, self.fmt) #left eR = eR.to_bytes(size,'little') R = curve.decode_point(eR) hasher = self._hasher() eA = curve.encode_point(pu_key.W) hasher.update(eR+eA+msg) h = hasher.digest() h = int.from_bytes(h,'little') h = h%n A = pu_key.W left = R+h*A #right right = S*curve.generator return left == right
if __name__ == "__main__": try: ### EDDSA cv = Curve.get_curve('Ed25519') # public key # x: 74ad28205b4f384bc0813e6585864e528085f91fb6a5096f244ae01e57de43ae # y: 0c66f42af155cdc08c96c42ecf2c989cbc7e1b4da70ab7925a8943e8c317403d pu_key = ECPublicKey(Point(0x74ad28205b4f384bc0813e6585864e528085f91fb6a5096f244ae01e57de43ae, 0x0c66f42af155cdc08c96c42ecf2c989cbc7e1b4da70ab7925a8943e8c317403d, cv)) # private key # s: 0x4ccd089b28ff96da9db6c346ec114e0f5b8a319f35aba624da8cf6ed4fb8a6fb pv_key = ECPrivateKey(0x4ccd089b28ff96da9db6c346ec114e0f5b8a319f35aba624da8cf6ed4fb8a6fb, cv) # sig: # 0x92a009a9f0d4cab8720e820b5f642540a2b27b5416503f8fb3762223ebdb69da # 0x085ac1e43e15996e458f3613d0f11d8c387b2eaeb4302aeeb00d291612bb0c00 expected_sig = int(0x92a009a9f0d4cab8720e820b5f642540a2b27b5416503f8fb3762223ebdb69da085ac1e43e15996e458f3613d0f11d8c387b2eaeb4302aeeb00d291612bb0c00) expected_sig = expected_sig.to_bytes(64,'big') #msg: # 72 msg = int(0x72) msg = msg.to_bytes(1,'big') signer = EDDSA(hashlib.sha512) sig = signer.sign(msg,pv_key) assert(sig == expected_sig) assert(signer.verify(msg,expected_sig,pu_key)) ##OK! print("All internal assert OK!") finally: pass