def generate(algorithm, **kwargs): """ Generates new private-public key pair for given algorithm (string like 'rsa','ec','gost2001') and algorithm-specific parameters. Algorithm specific paramteers for RSA: rsa_keygen_bits=number - size of key to be generated rsa_keygen_pubexp - RSA public expontent(default 65537) Algorithm specific parameters for DSA,DH and EC paramsfrom=PKey object copy parameters of newly generated key from existing key Algorithm specific parameters for GOST2001 paramset= paramset name where name is one of 'A','B','C','XA','XB','test' paramsfrom does work too """ tmpeng = c_void_p(None) if isinstance(algorithm, chartype): alg = algorithm.encode("ascii") else: alg = algorithm ameth = libcrypto.EVP_PKEY_asn1_find_str(byref(tmpeng), alg, -1) if ameth is None: raise PKeyError("Algorithm %s not foind\n" % (algorithm)) clear_err_stack() pkey_id = c_int(0) libcrypto.EVP_PKEY_asn1_get0_info(byref(pkey_id), None, None, None, None, ameth) #libcrypto.ENGINE_finish(tmpeng) if "paramsfrom" in kwargs: ctx = libcrypto.EVP_PKEY_CTX_new(kwargs["paramsfrom"].key, None) else: ctx = libcrypto.EVP_PKEY_CTX_new_id(pkey_id, None) # FIXME support EC curve as keyword param by invoking paramgen # operation if ctx is None: raise PKeyError("Creating context for key type %d" % (pkey_id.value)) if libcrypto.EVP_PKEY_keygen_init(ctx) <= 0: raise PKeyError("keygen_init") PKey._configure_context(ctx, kwargs, ["paramsfrom"]) key = c_void_p(None) if libcrypto.EVP_PKEY_keygen(ctx, byref(key)) <= 0: raise PKeyError("Error generating key") libcrypto.EVP_PKEY_CTX_free(ctx) return PKey(ptr=key, cansign=True)
def verify(self, digest, signature, **kwargs): """ Verifies given signature on given digest Returns True if Ok, False if don't match Keyword arguments allows to set algorithm-specific parameters """ ctx = libcrypto.EVP_PKEY_CTX_new(self.key, None) if ctx is None: raise PKeyError("Initailizing verify context") if libcrypto.EVP_PKEY_verify_init(ctx) < 1: raise PKeyError("verify_init") self._configure_context(ctx, kwargs) ret = libcrypto.EVP_PKEY_verify(ctx, signature, len(signature), digest, len(digest)) if ret < 0: raise PKeyError("Signature verification") libcrypto.EVP_PKEY_CTX_free(ctx) return ret > 0
def sign(self, digest, **kwargs): """ Signs given digest and retirns signature Keyword arguments allows to set various algorithm-specific parameters. See pkeyutl(1) manual. """ ctx = libcrypto.EVP_PKEY_CTX_new(self.key, None) if ctx is None: raise PKeyError("Initailizing sign context") if libcrypto.EVP_PKEY_sign_init(ctx) < 1: raise PKeyError("sign_init") self._configure_context(ctx, kwargs) # Find out signature size siglen = c_long(0) if libcrypto.EVP_PKEY_sign(ctx, None, byref(siglen), digest, len(digest)) < 1: raise PKeyError("computing signature length") sig = create_string_buffer(siglen.value) if libcrypto.EVP_PKEY_sign(ctx, sig, byref(siglen), digest, len(digest)) < 1: raise PKeyError("signing") libcrypto.EVP_PKEY_CTX_free(ctx) return sig.raw[:int(siglen.value)]
def derive(self, peerkey, **kwargs): """ Derives shared key (DH,ECDH,VKO 34.10). Requires private key available @param peerkey - other key (may be public only) Keyword parameters are algorithm-specific """ if not self.cansign: raise ValueError("No private key available") ctx = libcrypto.EVP_PKEY_CTX_new(self.key, None) if ctx is None: raise PKeyError("Initailizing derive context") if libcrypto.EVP_PKEY_derive_init(ctx) < 1: raise PKeyError("derive_init") # This is workaround around missing functionality in GOST engine # it provides only numeric control command to set UKM, not # string one. self._configure_context(ctx, kwargs, ["ukm"]) if libcrypto.EVP_PKEY_derive_set_peer(ctx, peerkey.key) <= 0: raise PKeyError("Cannot set peer key") if "ukm" in kwargs: # We just hardcode numeric command to set UKM here if libcrypto.EVP_PKEY_CTX_ctrl(ctx, -1, 1 << 10, 8, 8, kwargs["ukm"]) <= 0: raise PKeyError("Cannot set UKM") keylen = c_long(0) if libcrypto.EVP_PKEY_derive(ctx, None, byref(keylen)) <= 0: raise PKeyError("computing shared key length") buf = create_string_buffer(keylen.value) if libcrypto.EVP_PKEY_derive(ctx, buf, byref(keylen)) <= 0: raise PKeyError("computing actual shared key") libcrypto.EVP_PKEY_CTX_free(ctx) return buf.raw[:int(keylen.value)]