charm-crypto-framework 0.61.1__cp313-cp313-macosx_10_13_universal2.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- charm/__init__.py +5 -0
- charm/adapters/__init__.py +0 -0
- charm/adapters/abenc_adapt_hybrid.py +90 -0
- charm/adapters/dabenc_adapt_hybrid.py +145 -0
- charm/adapters/ibenc_adapt_hybrid.py +72 -0
- charm/adapters/ibenc_adapt_identityhash.py +80 -0
- charm/adapters/kpabenc_adapt_hybrid.py +91 -0
- charm/adapters/pkenc_adapt_bchk05.py +121 -0
- charm/adapters/pkenc_adapt_chk04.py +91 -0
- charm/adapters/pkenc_adapt_hybrid.py +98 -0
- charm/adapters/pksig_adapt_naor01.py +89 -0
- charm/config.py +7 -0
- charm/core/__init__.py +0 -0
- charm/core/benchmark/benchmark_util.c +353 -0
- charm/core/benchmark/benchmark_util.h +61 -0
- charm/core/benchmark/benchmarkmodule.c +476 -0
- charm/core/benchmark/benchmarkmodule.h +162 -0
- charm/core/benchmark.cpython-313-darwin.so +0 -0
- charm/core/crypto/AES/AES.c +1464 -0
- charm/core/crypto/AES.cpython-313-darwin.so +0 -0
- charm/core/crypto/DES/DES.c +113 -0
- charm/core/crypto/DES.cpython-313-darwin.so +0 -0
- charm/core/crypto/DES3/DES3.c +26 -0
- charm/core/crypto/DES3.cpython-313-darwin.so +0 -0
- charm/core/crypto/__init__.py +0 -0
- charm/core/crypto/cryptobase/XOR.c +80 -0
- charm/core/crypto/cryptobase/_counter.c +496 -0
- charm/core/crypto/cryptobase/_counter.h +54 -0
- charm/core/crypto/cryptobase/block_template.c +900 -0
- charm/core/crypto/cryptobase/block_template.h +69 -0
- charm/core/crypto/cryptobase/cryptobasemodule.c +220 -0
- charm/core/crypto/cryptobase/libtom/tomcrypt.h +90 -0
- charm/core/crypto/cryptobase/libtom/tomcrypt_argchk.h +44 -0
- charm/core/crypto/cryptobase/libtom/tomcrypt_cfg.h +186 -0
- charm/core/crypto/cryptobase/libtom/tomcrypt_cipher.h +941 -0
- charm/core/crypto/cryptobase/libtom/tomcrypt_custom.h +556 -0
- charm/core/crypto/cryptobase/libtom/tomcrypt_des.c +1912 -0
- charm/core/crypto/cryptobase/libtom/tomcrypt_hash.h +407 -0
- charm/core/crypto/cryptobase/libtom/tomcrypt_mac.h +496 -0
- charm/core/crypto/cryptobase/libtom/tomcrypt_macros.h +435 -0
- charm/core/crypto/cryptobase/libtom/tomcrypt_math.h +534 -0
- charm/core/crypto/cryptobase/libtom/tomcrypt_misc.h +103 -0
- charm/core/crypto/cryptobase/libtom/tomcrypt_pk.h +653 -0
- charm/core/crypto/cryptobase/libtom/tomcrypt_pkcs.h +90 -0
- charm/core/crypto/cryptobase/libtom/tomcrypt_prng.h +199 -0
- charm/core/crypto/cryptobase/stream_template.c +271 -0
- charm/core/crypto/cryptobase/strxor.c +229 -0
- charm/core/crypto/cryptobase.cpython-313-darwin.so +0 -0
- charm/core/engine/__init__.py +5 -0
- charm/core/engine/protocol.py +293 -0
- charm/core/engine/util.py +174 -0
- charm/core/math/__init__.py +0 -0
- charm/core/math/elliptic_curve/ecmodule.c +1986 -0
- charm/core/math/elliptic_curve/ecmodule.h +230 -0
- charm/core/math/elliptic_curve.cpython-313-darwin.so +0 -0
- charm/core/math/elliptic_curve.pyi +63 -0
- charm/core/math/integer/integermodule.c +2539 -0
- charm/core/math/integer/integermodule.h +145 -0
- charm/core/math/integer.cpython-313-darwin.so +0 -0
- charm/core/math/integer.pyi +76 -0
- charm/core/math/pairing/miracl/miracl_config.h +37 -0
- charm/core/math/pairing/miracl/miracl_interface.h +118 -0
- charm/core/math/pairing/miracl/miracl_interface2.h +126 -0
- charm/core/math/pairing/miracl/pairingmodule2.c +2094 -0
- charm/core/math/pairing/miracl/pairingmodule2.h +307 -0
- charm/core/math/pairing/pairingmodule.c +2230 -0
- charm/core/math/pairing/pairingmodule.h +241 -0
- charm/core/math/pairing/relic/pairingmodule3.c +1853 -0
- charm/core/math/pairing/relic/pairingmodule3.h +233 -0
- charm/core/math/pairing/relic/relic_interface.c +1337 -0
- charm/core/math/pairing/relic/relic_interface.h +217 -0
- charm/core/math/pairing/relic/test_relic.c +171 -0
- charm/core/math/pairing.cpython-313-darwin.so +0 -0
- charm/core/math/pairing.pyi +69 -0
- charm/core/utilities/base64.c +248 -0
- charm/core/utilities/base64.h +15 -0
- charm/schemes/__init__.py +0 -0
- charm/schemes/abenc/__init__.py +0 -0
- charm/schemes/abenc/abenc_accountability_jyjxgd20.py +647 -0
- charm/schemes/abenc/abenc_bsw07.py +146 -0
- charm/schemes/abenc/abenc_ca_cpabe_ar17.py +684 -0
- charm/schemes/abenc/abenc_dacmacs_yj14.py +298 -0
- charm/schemes/abenc/abenc_lsw08.py +159 -0
- charm/schemes/abenc/abenc_maabe_rw15.py +236 -0
- charm/schemes/abenc/abenc_maabe_yj14.py +297 -0
- charm/schemes/abenc/abenc_tbpre_lww14.py +309 -0
- charm/schemes/abenc/abenc_unmcpabe_yahk14.py +223 -0
- charm/schemes/abenc/abenc_waters09.py +144 -0
- charm/schemes/abenc/abenc_yct14.py +208 -0
- charm/schemes/abenc/abenc_yllc15.py +178 -0
- charm/schemes/abenc/ac17.py +248 -0
- charm/schemes/abenc/bsw07.py +141 -0
- charm/schemes/abenc/cgw15.py +277 -0
- charm/schemes/abenc/dabe_aw11.py +204 -0
- charm/schemes/abenc/dfa_fe12.py +144 -0
- charm/schemes/abenc/pk_hve08.py +179 -0
- charm/schemes/abenc/waters11.py +143 -0
- charm/schemes/aggrsign_MuSig.py +150 -0
- charm/schemes/aggrsign_bls.py +267 -0
- charm/schemes/blindsig_ps16.py +654 -0
- charm/schemes/chamhash_adm05.py +113 -0
- charm/schemes/chamhash_rsa_hw09.py +100 -0
- charm/schemes/commit/__init__.py +0 -0
- charm/schemes/commit/commit_gs08.py +77 -0
- charm/schemes/commit/commit_pedersen92.py +53 -0
- charm/schemes/encap_bchk05.py +62 -0
- charm/schemes/grpsig/__init__.py +0 -0
- charm/schemes/grpsig/groupsig_bgls04.py +114 -0
- charm/schemes/grpsig/groupsig_bgls04_var.py +115 -0
- charm/schemes/hibenc/__init__.py +0 -0
- charm/schemes/hibenc/hibenc_bb04.py +105 -0
- charm/schemes/hibenc/hibenc_lew11.py +193 -0
- charm/schemes/ibenc/__init__.py +0 -0
- charm/schemes/ibenc/clpkc_rp03.py +119 -0
- charm/schemes/ibenc/ibenc_CW13_z.py +168 -0
- charm/schemes/ibenc/ibenc_bb03.py +94 -0
- charm/schemes/ibenc/ibenc_bf01.py +121 -0
- charm/schemes/ibenc/ibenc_ckrs09.py +120 -0
- charm/schemes/ibenc/ibenc_cllww12_z.py +172 -0
- charm/schemes/ibenc/ibenc_lsw08.py +120 -0
- charm/schemes/ibenc/ibenc_sw05.py +238 -0
- charm/schemes/ibenc/ibenc_waters05.py +144 -0
- charm/schemes/ibenc/ibenc_waters05_z.py +164 -0
- charm/schemes/ibenc/ibenc_waters09.py +107 -0
- charm/schemes/ibenc/ibenc_waters09_z.py +147 -0
- charm/schemes/joye_scheme.py +106 -0
- charm/schemes/lem_scheme.py +207 -0
- charm/schemes/pk_fre_ccv11.py +107 -0
- charm/schemes/pk_vrf.py +127 -0
- charm/schemes/pkenc/__init__.py +0 -0
- charm/schemes/pkenc/pkenc_cs98.py +108 -0
- charm/schemes/pkenc/pkenc_elgamal85.py +122 -0
- charm/schemes/pkenc/pkenc_gm82.py +98 -0
- charm/schemes/pkenc/pkenc_paillier99.py +118 -0
- charm/schemes/pkenc/pkenc_rabin.py +254 -0
- charm/schemes/pkenc/pkenc_rsa.py +186 -0
- charm/schemes/pksig/__init__.py +0 -0
- charm/schemes/pksig/pksig_CW13_z.py +135 -0
- charm/schemes/pksig/pksig_bls04.py +87 -0
- charm/schemes/pksig/pksig_boyen.py +156 -0
- charm/schemes/pksig/pksig_chch.py +97 -0
- charm/schemes/pksig/pksig_chp.py +70 -0
- charm/schemes/pksig/pksig_cl03.py +150 -0
- charm/schemes/pksig/pksig_cl04.py +87 -0
- charm/schemes/pksig/pksig_cllww12_z.py +142 -0
- charm/schemes/pksig/pksig_cyh.py +132 -0
- charm/schemes/pksig/pksig_dsa.py +76 -0
- charm/schemes/pksig/pksig_ecdsa.py +71 -0
- charm/schemes/pksig/pksig_hess.py +104 -0
- charm/schemes/pksig/pksig_hw.py +110 -0
- charm/schemes/pksig/pksig_lamport.py +63 -0
- charm/schemes/pksig/pksig_ps01.py +135 -0
- charm/schemes/pksig/pksig_ps02.py +124 -0
- charm/schemes/pksig/pksig_ps03.py +119 -0
- charm/schemes/pksig/pksig_rsa_hw09.py +206 -0
- charm/schemes/pksig/pksig_schnorr91.py +77 -0
- charm/schemes/pksig/pksig_waters.py +115 -0
- charm/schemes/pksig/pksig_waters05.py +121 -0
- charm/schemes/pksig/pksig_waters09.py +121 -0
- charm/schemes/pre_mg07.py +150 -0
- charm/schemes/prenc/pre_afgh06.py +126 -0
- charm/schemes/prenc/pre_bbs98.py +123 -0
- charm/schemes/prenc/pre_nal16.py +216 -0
- charm/schemes/protocol_a01.py +272 -0
- charm/schemes/protocol_ao00.py +215 -0
- charm/schemes/protocol_cns07.py +274 -0
- charm/schemes/protocol_schnorr91.py +125 -0
- charm/schemes/sigma1.py +64 -0
- charm/schemes/sigma2.py +129 -0
- charm/schemes/sigma3.py +126 -0
- charm/schemes/threshold/__init__.py +59 -0
- charm/schemes/threshold/dkls23_dkg.py +556 -0
- charm/schemes/threshold/dkls23_presign.py +1089 -0
- charm/schemes/threshold/dkls23_sign.py +761 -0
- charm/schemes/threshold/xrpl_wallet.py +967 -0
- charm/test/__init__.py +0 -0
- charm/test/adapters/__init__.py +0 -0
- charm/test/adapters/abenc_adapt_hybrid_test.py +29 -0
- charm/test/adapters/dabenc_adapt_hybrid_test.py +56 -0
- charm/test/adapters/ibenc_adapt_hybrid_test.py +36 -0
- charm/test/adapters/ibenc_adapt_identityhash_test.py +32 -0
- charm/test/adapters/kpabenc_adapt_hybrid_test.py +30 -0
- charm/test/benchmark/abenc_yllc15_bench.py +92 -0
- charm/test/benchmark/benchmark_test.py +148 -0
- charm/test/benchmark_threshold.py +260 -0
- charm/test/conftest.py +38 -0
- charm/test/fuzz/__init__.py +1 -0
- charm/test/fuzz/conftest.py +5 -0
- charm/test/fuzz/fuzz_policy_parser.py +76 -0
- charm/test/fuzz/fuzz_serialization.py +83 -0
- charm/test/schemes/__init__.py +0 -0
- charm/test/schemes/abenc/__init__.py +0 -0
- charm/test/schemes/abenc/abenc_bsw07_test.py +39 -0
- charm/test/schemes/abenc/abenc_dacmacs_yj14_test.py +16 -0
- charm/test/schemes/abenc/abenc_lsw08_test.py +33 -0
- charm/test/schemes/abenc/abenc_maabe_yj14_test.py +16 -0
- charm/test/schemes/abenc/abenc_tbpre_lww14_test.py +16 -0
- charm/test/schemes/abenc/abenc_waters09_test.py +38 -0
- charm/test/schemes/abenc/abenc_yllc15_test.py +74 -0
- charm/test/schemes/chamhash_adm05_test.py +31 -0
- charm/test/schemes/chamhash_rsa_hw09_test.py +29 -0
- charm/test/schemes/commit/__init__.py +0 -0
- charm/test/schemes/commit/commit_gs08_test.py +24 -0
- charm/test/schemes/commit/commit_pedersen92_test.py +26 -0
- charm/test/schemes/dabe_aw11_test.py +45 -0
- charm/test/schemes/encap_bchk05_test.py +21 -0
- charm/test/schemes/grpsig/__init__.py +0 -0
- charm/test/schemes/grpsig/groupsig_bgls04_test.py +35 -0
- charm/test/schemes/grpsig/groupsig_bgls04_var_test.py +39 -0
- charm/test/schemes/hibenc/__init__.py +0 -0
- charm/test/schemes/hibenc/hibenc_bb04_test.py +28 -0
- charm/test/schemes/ibenc/__init__.py +0 -0
- charm/test/schemes/ibenc/ibenc_bb03_test.py +26 -0
- charm/test/schemes/ibenc/ibenc_bf01_test.py +24 -0
- charm/test/schemes/ibenc/ibenc_ckrs09_test.py +25 -0
- charm/test/schemes/ibenc/ibenc_lsw08_test.py +31 -0
- charm/test/schemes/ibenc/ibenc_sw05_test.py +32 -0
- charm/test/schemes/ibenc/ibenc_waters05_test.py +31 -0
- charm/test/schemes/ibenc/ibenc_waters09_test.py +27 -0
- charm/test/schemes/pk_vrf_test.py +29 -0
- charm/test/schemes/pkenc/__init__.py +0 -0
- charm/test/schemes/pkenc_test.py +255 -0
- charm/test/schemes/pksig/__init__.py +0 -0
- charm/test/schemes/pksig_test.py +376 -0
- charm/test/schemes/rsa_alg_test.py +340 -0
- charm/test/schemes/threshold_test.py +1792 -0
- charm/test/serialize/__init__.py +0 -0
- charm/test/serialize/serialize_test.py +40 -0
- charm/test/toolbox/__init__.py +0 -0
- charm/test/toolbox/conversion_test.py +30 -0
- charm/test/toolbox/ecgroup_test.py +53 -0
- charm/test/toolbox/integer_arithmetic_test.py +441 -0
- charm/test/toolbox/paddingschemes_test.py +238 -0
- charm/test/toolbox/policy_parser_stress_test.py +969 -0
- charm/test/toolbox/secretshare_test.py +28 -0
- charm/test/toolbox/symcrypto_test.py +108 -0
- charm/test/toolbox/test_policy_expression.py +16 -0
- charm/test/vectors/__init__.py +1 -0
- charm/test/vectors/test_bls_vectors.py +289 -0
- charm/test/vectors/test_pedersen_vectors.py +315 -0
- charm/test/vectors/test_schnorr_vectors.py +368 -0
- charm/test/zkp_compiler/__init__.py +9 -0
- charm/test/zkp_compiler/benchmark_zkp.py +258 -0
- charm/test/zkp_compiler/test_and_proof.py +240 -0
- charm/test/zkp_compiler/test_batch_verify.py +248 -0
- charm/test/zkp_compiler/test_dleq_proof.py +264 -0
- charm/test/zkp_compiler/test_or_proof.py +231 -0
- charm/test/zkp_compiler/test_proof_serialization.py +121 -0
- charm/test/zkp_compiler/test_range_proof.py +241 -0
- charm/test/zkp_compiler/test_representation_proof.py +325 -0
- charm/test/zkp_compiler/test_schnorr_proof.py +221 -0
- charm/test/zkp_compiler/test_thread_safety.py +169 -0
- charm/test/zkp_compiler/test_zkp_parser.py +139 -0
- charm/toolbox/ABEnc.py +26 -0
- charm/toolbox/ABEncMultiAuth.py +66 -0
- charm/toolbox/ABEnumeric.py +800 -0
- charm/toolbox/Commit.py +24 -0
- charm/toolbox/DFA.py +89 -0
- charm/toolbox/FSA.py +1254 -0
- charm/toolbox/Hash.py +39 -0
- charm/toolbox/IBEnc.py +62 -0
- charm/toolbox/IBSig.py +64 -0
- charm/toolbox/PKEnc.py +66 -0
- charm/toolbox/PKSig.py +56 -0
- charm/toolbox/PREnc.py +32 -0
- charm/toolbox/ZKProof.py +289 -0
- charm/toolbox/__init__.py +0 -0
- charm/toolbox/bitstring.py +49 -0
- charm/toolbox/broadcast.py +220 -0
- charm/toolbox/conversion.py +100 -0
- charm/toolbox/eccurve.py +149 -0
- charm/toolbox/ecgroup.py +143 -0
- charm/toolbox/enum.py +60 -0
- charm/toolbox/hash_module.py +91 -0
- charm/toolbox/integergroup.py +323 -0
- charm/toolbox/iterate.py +22 -0
- charm/toolbox/matrixops.py +76 -0
- charm/toolbox/mpc_utils.py +296 -0
- charm/toolbox/msp.py +175 -0
- charm/toolbox/mta.py +985 -0
- charm/toolbox/node.py +120 -0
- charm/toolbox/ot/__init__.py +22 -0
- charm/toolbox/ot/base_ot.py +374 -0
- charm/toolbox/ot/dpf.py +642 -0
- charm/toolbox/ot/mpfss.py +228 -0
- charm/toolbox/ot/ot_extension.py +589 -0
- charm/toolbox/ot/silent_ot.py +378 -0
- charm/toolbox/paddingschemes.py +423 -0
- charm/toolbox/paddingschemes_test.py +238 -0
- charm/toolbox/pairingcurves.py +85 -0
- charm/toolbox/pairinggroup.py +186 -0
- charm/toolbox/policy_expression_spec.py +70 -0
- charm/toolbox/policytree.py +189 -0
- charm/toolbox/reCompiler.py +346 -0
- charm/toolbox/redundancyschemes.py +65 -0
- charm/toolbox/schemebase.py +188 -0
- charm/toolbox/secretshare.py +104 -0
- charm/toolbox/secretutil.py +174 -0
- charm/toolbox/securerandom.py +73 -0
- charm/toolbox/sigmaprotocol.py +46 -0
- charm/toolbox/specialprimes.py +45 -0
- charm/toolbox/symcrypto.py +279 -0
- charm/toolbox/threshold_sharing.py +553 -0
- charm/toolbox/xmlserialize.py +94 -0
- charm/toolbox/zknode.py +105 -0
- charm/zkp_compiler/__init__.py +89 -0
- charm/zkp_compiler/and_proof.py +460 -0
- charm/zkp_compiler/batch_verify.py +324 -0
- charm/zkp_compiler/dleq_proof.py +423 -0
- charm/zkp_compiler/or_proof.py +305 -0
- charm/zkp_compiler/range_proof.py +417 -0
- charm/zkp_compiler/representation_proof.py +466 -0
- charm/zkp_compiler/schnorr_proof.py +273 -0
- charm/zkp_compiler/thread_safe.py +150 -0
- charm/zkp_compiler/zk_demo.py +489 -0
- charm/zkp_compiler/zkp_factory.py +330 -0
- charm/zkp_compiler/zkp_generator.py +370 -0
- charm/zkp_compiler/zkparser.py +269 -0
- charm_crypto_framework-0.61.1.dist-info/METADATA +337 -0
- charm_crypto_framework-0.61.1.dist-info/RECORD +323 -0
- charm_crypto_framework-0.61.1.dist-info/WHEEL +5 -0
- charm_crypto_framework-0.61.1.dist-info/licenses/LICENSE.txt +165 -0
- charm_crypto_framework-0.61.1.dist-info/top_level.txt +1 -0
|
@@ -0,0 +1,1986 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Charm-Crypto is a framework for rapidly prototyping cryptosystems.
|
|
3
|
+
*
|
|
4
|
+
* Charm-Crypto is free software; you can redistribute it and/or
|
|
5
|
+
* modify it under the terms of the GNU Lesser General Public
|
|
6
|
+
* License as published by the Free Software Foundation; either
|
|
7
|
+
* version 2.1 of the License, or (at your option) any later version.
|
|
8
|
+
*
|
|
9
|
+
* Charm-Crypto is distributed in the hope that it will be useful,
|
|
10
|
+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
11
|
+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
12
|
+
* Lesser General Public License for more details.
|
|
13
|
+
*
|
|
14
|
+
* You should have received a copy of the GNU Lesser General Public License
|
|
15
|
+
* along with Charm-Crypto. If not, see <http://www.gnu.org/licenses/>.
|
|
16
|
+
*
|
|
17
|
+
* Please contact the charm-crypto dev team at support@charm-crypto.com
|
|
18
|
+
* for any questions.
|
|
19
|
+
*/
|
|
20
|
+
|
|
21
|
+
/*
|
|
22
|
+
* @file ecmodule.c
|
|
23
|
+
*
|
|
24
|
+
* @brief charm interface over OpenSSL Ellipic-curve module
|
|
25
|
+
*
|
|
26
|
+
* @author jakinye3@jhu.edu
|
|
27
|
+
*
|
|
28
|
+
************************************************************************/
|
|
29
|
+
|
|
30
|
+
#include "ecmodule.h"
|
|
31
|
+
|
|
32
|
+
/*
|
|
33
|
+
* Python 3.13+ made Py_IsFinalizing() public and removed _Py_IsFinalizing().
|
|
34
|
+
* For older versions, we need to use the private _Py_IsFinalizing().
|
|
35
|
+
*/
|
|
36
|
+
#if PY_MINOR_VERSION >= 13
|
|
37
|
+
#define CHARM_PY_IS_FINALIZING() Py_IsFinalizing()
|
|
38
|
+
#else
|
|
39
|
+
#define CHARM_PY_IS_FINALIZING() _Py_IsFinalizing()
|
|
40
|
+
#endif
|
|
41
|
+
|
|
42
|
+
void printf_buffer_as_hex(uint8_t * data, size_t len)
|
|
43
|
+
{
|
|
44
|
+
#ifdef DEBUG
|
|
45
|
+
size_t i;
|
|
46
|
+
|
|
47
|
+
for (i = 0; i < len; i++) {
|
|
48
|
+
printf("%02x ", data[i]);
|
|
49
|
+
}
|
|
50
|
+
printf("\n");
|
|
51
|
+
#endif
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
void setBigNum(PyLongObject *obj, BIGNUM **value) {
|
|
55
|
+
// convert Python long object to temporary decimal string
|
|
56
|
+
#if PY_MAJOR_VERSION >= 3 && PY_MINOR_VERSION >= 13
|
|
57
|
+
/*
|
|
58
|
+
* For Python 3.13+: _PyLong_Format was removed in Python 3.13.
|
|
59
|
+
* Use PyObject_Str to convert the integer to a string.
|
|
60
|
+
*/
|
|
61
|
+
PyObject *strObj = PyObject_Str((PyObject *)obj);
|
|
62
|
+
const char *tmp_str = PyUnicode_AsUTF8(strObj);
|
|
63
|
+
#elif PY_MAJOR_VERSION >= 3
|
|
64
|
+
/*
|
|
65
|
+
* For Python 3.3-3.12: Use _PyLong_Format (private API).
|
|
66
|
+
* Use PyUnicode_AsUTF8 to get a proper null-terminated UTF-8 string.
|
|
67
|
+
*/
|
|
68
|
+
PyObject *strObj = _PyLong_Format((PyObject *)obj, 10);
|
|
69
|
+
const char *tmp_str = PyUnicode_AsUTF8(strObj);
|
|
70
|
+
#else
|
|
71
|
+
/* for Python 2.x */
|
|
72
|
+
PyObject *strObj = _PyLong_Format((PyObject *)obj, 10, 0, 0);
|
|
73
|
+
const char *tmp_str = PyString_AS_STRING(strObj);
|
|
74
|
+
#endif
|
|
75
|
+
|
|
76
|
+
// convert decimal string to OpenSSL bignum
|
|
77
|
+
BN_dec2bn(value, tmp_str);
|
|
78
|
+
|
|
79
|
+
// free temporary decimal string
|
|
80
|
+
Py_DECREF(strObj);
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
/*!
|
|
84
|
+
* Hash a null-terminated string to a byte array.
|
|
85
|
+
*
|
|
86
|
+
* @param input_buf The input buffer.
|
|
87
|
+
* @param input_len The input buffer length (in bytes).
|
|
88
|
+
* @param output_buf A pre-allocated output buffer of size hash_len.
|
|
89
|
+
* @param hash_len Length of the output hash (in bytes). Should be approximately bit size of curve group order.
|
|
90
|
+
* @param hash_prefix prefix for hash function.
|
|
91
|
+
*/
|
|
92
|
+
int hash_to_bytes(uint8_t *input_buf, int input_len, uint8_t *output_buf, int hash_len, uint8_t hash_prefix)
|
|
93
|
+
{
|
|
94
|
+
EVP_MD_CTX *ctx = NULL;
|
|
95
|
+
int i, new_input_len = input_len + 2; // extra byte for prefix
|
|
96
|
+
uint8_t first_block = 0;
|
|
97
|
+
uint8_t new_input[new_input_len+1];
|
|
98
|
+
unsigned int md_len = 0;
|
|
99
|
+
|
|
100
|
+
memset(new_input, 0, new_input_len+1);
|
|
101
|
+
new_input[0] = first_block; // block number (always 0 by default)
|
|
102
|
+
new_input[1] = hash_prefix; // set hash prefix
|
|
103
|
+
memcpy((uint8_t *)(new_input+2), input_buf, input_len); // copy input bytes
|
|
104
|
+
|
|
105
|
+
debug("new input => \n");
|
|
106
|
+
printf_buffer_as_hex(new_input, new_input_len);
|
|
107
|
+
// prepare output buf
|
|
108
|
+
memset(output_buf, 0, hash_len);
|
|
109
|
+
|
|
110
|
+
ctx = EVP_MD_CTX_new();
|
|
111
|
+
if (ctx == NULL) return FALSE;
|
|
112
|
+
|
|
113
|
+
if (hash_len <= HASH_LEN) {
|
|
114
|
+
uint8_t md[HASH_LEN+1];
|
|
115
|
+
EVP_DigestInit_ex(ctx, EVP_sha256(), NULL);
|
|
116
|
+
EVP_DigestUpdate(ctx, new_input, new_input_len);
|
|
117
|
+
EVP_DigestFinal_ex(ctx, md, &md_len);
|
|
118
|
+
memcpy(output_buf, md, hash_len);
|
|
119
|
+
}
|
|
120
|
+
else {
|
|
121
|
+
// apply variable-size hash technique to get desired size
|
|
122
|
+
// determine block count.
|
|
123
|
+
int blocks = (int) ceil(((double) hash_len) / HASH_LEN);
|
|
124
|
+
debug("Num blocks needed: %d\n", blocks);
|
|
125
|
+
uint8_t md[HASH_LEN+1];
|
|
126
|
+
uint8_t md2[(blocks * HASH_LEN)+1];
|
|
127
|
+
uint8_t *target_buf = md2;
|
|
128
|
+
for(i = 0; i < blocks; i++) {
|
|
129
|
+
/* compute digest = SHA-2( i || prefix || input_buf ) || ... || SHA-2( n-1 || prefix || input_buf ) */
|
|
130
|
+
target_buf += (i * HASH_LEN);
|
|
131
|
+
new_input[0] = (uint8_t) i;
|
|
132
|
+
EVP_DigestInit_ex(ctx, EVP_sha256(), NULL);
|
|
133
|
+
debug("input %d => ", i);
|
|
134
|
+
printf_buffer_as_hex(new_input, new_input_len);
|
|
135
|
+
EVP_DigestUpdate(ctx, new_input, new_input_len);
|
|
136
|
+
EVP_DigestFinal_ex(ctx, md, &md_len);
|
|
137
|
+
memcpy(target_buf, md, hash_len);
|
|
138
|
+
debug("block %d => ", i);
|
|
139
|
+
printf_buffer_as_hex(md, HASH_LEN);
|
|
140
|
+
memset(md, 0, HASH_LEN);
|
|
141
|
+
}
|
|
142
|
+
// copy back to caller
|
|
143
|
+
memcpy(output_buf, md2, hash_len);
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
EVP_MD_CTX_free(ctx);
|
|
147
|
+
return TRUE;
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
|
|
151
|
+
/*
|
|
152
|
+
* Create a new point with an existing group object
|
|
153
|
+
*/
|
|
154
|
+
ECElement *createNewPoint(GroupType type, ECGroup *gobj) {
|
|
155
|
+
if(type != ZR && type != G) return NULL;
|
|
156
|
+
ECElement *newObj = PyObject_New(ECElement, &ECType);
|
|
157
|
+
if(type == ZR) {
|
|
158
|
+
newObj->type = type;
|
|
159
|
+
newObj->elemZ = BN_new();
|
|
160
|
+
newObj->P = NULL;
|
|
161
|
+
}
|
|
162
|
+
else if(type == G) {
|
|
163
|
+
newObj->type = type;
|
|
164
|
+
newObj->P = EC_POINT_new(gobj->ec_group);
|
|
165
|
+
newObj->elemZ = NULL;
|
|
166
|
+
}
|
|
167
|
+
newObj->point_init = TRUE;
|
|
168
|
+
newObj->group = gobj; // gobj->group
|
|
169
|
+
Py_INCREF(newObj->group);
|
|
170
|
+
return newObj;
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
int ECElement_init(ECElement *self, PyObject *args, PyObject *kwds)
|
|
174
|
+
{
|
|
175
|
+
return 0;
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
|
|
179
|
+
void ECElement_dealloc(ECElement* self) {
|
|
180
|
+
/* clear structure */
|
|
181
|
+
if(self->point_init && self->type == G) { debug("clearing ec point.\n"); EC_POINT_free(self->P); }
|
|
182
|
+
if(self->point_init && self->type == ZR) { debug("clearing ec zr element.\n"); BN_free(self->elemZ); }
|
|
183
|
+
Py_XDECREF(self->group);
|
|
184
|
+
Py_TYPE(self)->tp_free((PyObject*)self);
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
PyObject *ECElement_new(PyTypeObject *type, PyObject *args, PyObject *kwds) {
|
|
188
|
+
ECElement *self;
|
|
189
|
+
|
|
190
|
+
self = (ECElement *)type->tp_alloc(type, 0);
|
|
191
|
+
if (self != NULL) {
|
|
192
|
+
/* initialize fields here */
|
|
193
|
+
debug("object created...\n");
|
|
194
|
+
self->type = NONE_G;
|
|
195
|
+
self->group = NULL;
|
|
196
|
+
self->P = NULL;
|
|
197
|
+
self->elemZ = NULL;
|
|
198
|
+
self->point_init = FALSE;
|
|
199
|
+
}
|
|
200
|
+
return (PyObject *) self;
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
void ECGroup_dealloc(ECGroup *self)
|
|
204
|
+
{
|
|
205
|
+
if(self->group_init == TRUE && self->ec_group != NULL) {
|
|
206
|
+
// Defensive: Add NULL checks before cleanup to prevent crashes
|
|
207
|
+
// Release GIL during cleanup operations for thread safety
|
|
208
|
+
Py_BEGIN_ALLOW_THREADS;
|
|
209
|
+
|
|
210
|
+
debug("clearing ec group struct.\n");
|
|
211
|
+
if(self->ec_group != NULL) {
|
|
212
|
+
EC_GROUP_clear_free(self->ec_group);
|
|
213
|
+
self->ec_group = NULL;
|
|
214
|
+
}
|
|
215
|
+
if(self->order != NULL) {
|
|
216
|
+
BN_free(self->order);
|
|
217
|
+
self->order = NULL;
|
|
218
|
+
}
|
|
219
|
+
if(self->ctx != NULL) {
|
|
220
|
+
BN_CTX_free(self->ctx);
|
|
221
|
+
self->ctx = NULL;
|
|
222
|
+
}
|
|
223
|
+
self->group_init = FALSE;
|
|
224
|
+
|
|
225
|
+
Py_END_ALLOW_THREADS;
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
#ifdef BENCHMARK_ENABLED
|
|
229
|
+
if(self->dBench != NULL) {
|
|
230
|
+
Py_CLEAR(self->dBench);
|
|
231
|
+
if(self->gBench != NULL) {
|
|
232
|
+
Py_CLEAR(self->gBench);
|
|
233
|
+
}
|
|
234
|
+
}
|
|
235
|
+
#endif
|
|
236
|
+
debug("Releasing ECGroup object!\n");
|
|
237
|
+
Py_TYPE(self)->tp_free((PyObject *) self);
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
PyObject *ECGroup_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
|
|
241
|
+
{
|
|
242
|
+
ECGroup *self = (ECGroup *) type->tp_alloc(type, 0);
|
|
243
|
+
if(self != NULL) {
|
|
244
|
+
self->group_init = FALSE;
|
|
245
|
+
self->nid = -1;
|
|
246
|
+
self->ec_group = NULL;
|
|
247
|
+
self->order = BN_new();
|
|
248
|
+
self->ctx = BN_CTX_new();
|
|
249
|
+
#ifdef BENCHMARK_ENABLED
|
|
250
|
+
memset(self->bench_id, 0, ID_LEN);
|
|
251
|
+
self->dBench = NULL;
|
|
252
|
+
self->gBench = NULL;
|
|
253
|
+
#endif
|
|
254
|
+
}
|
|
255
|
+
|
|
256
|
+
return (PyObject *) self;
|
|
257
|
+
}
|
|
258
|
+
|
|
259
|
+
int ECGroup_init(ECGroup *self, PyObject *args, PyObject *kwds)
|
|
260
|
+
{
|
|
261
|
+
PyObject *pObj = NULL, *aObj = NULL, *bObj = NULL;
|
|
262
|
+
char *params = NULL, *param_string = NULL;
|
|
263
|
+
Py_ssize_t pf_len, ps_len;
|
|
264
|
+
int nid;
|
|
265
|
+
static char *kwlist[] = {"params", "param_string", "p", "a", "b", "nid", NULL};
|
|
266
|
+
|
|
267
|
+
if (! PyArg_ParseTupleAndKeywords(args, kwds, "|s#s#OOOi", kwlist,
|
|
268
|
+
¶ms, &pf_len, ¶m_string, &ps_len,
|
|
269
|
+
&pObj, &aObj, &bObj, &nid)) {
|
|
270
|
+
return -1;
|
|
271
|
+
}
|
|
272
|
+
|
|
273
|
+
debug("initializing object...\n");
|
|
274
|
+
if(pObj && aObj && bObj && !params && !param_string && !nid) {
|
|
275
|
+
// p, a, and b curve parameters are set...
|
|
276
|
+
if(!PyLong_Check(pObj) || !PyLong_Check(aObj) || !PyLong_Check(bObj))
|
|
277
|
+
{
|
|
278
|
+
return -1;
|
|
279
|
+
}
|
|
280
|
+
|
|
281
|
+
BIGNUM *p,*a,*b;
|
|
282
|
+
p = BN_new();
|
|
283
|
+
setBigNum((PyLongObject *) pObj, &p);
|
|
284
|
+
|
|
285
|
+
// make sure p is prime then continue loading a and b parameters for EC
|
|
286
|
+
if(BN_is_prime_ex(p, BN_prime_checks, self->ctx, NULL) != 1) {
|
|
287
|
+
debug("p is not prime.\n");
|
|
288
|
+
BN_free(p);
|
|
289
|
+
PyErr_SetString(PyECErrorObject, "p must be a prime integer.");
|
|
290
|
+
return -1;
|
|
291
|
+
}
|
|
292
|
+
|
|
293
|
+
a = BN_new();
|
|
294
|
+
b = BN_new();
|
|
295
|
+
setBigNum((PyLongObject *) aObj, &a);
|
|
296
|
+
setBigNum((PyLongObject *) bObj, &b);
|
|
297
|
+
debug("p (bn) is now '%s'\n", BN_bn2dec(p));
|
|
298
|
+
debug("a (bn) is now '%s'\n", BN_bn2dec(a));
|
|
299
|
+
debug("b (bn) is now '%s'\n", BN_bn2dec(b));
|
|
300
|
+
// now we can instantiate the ec_group
|
|
301
|
+
self->ec_group = EC_GROUP_new_curve_GFp(p, a, b, self->ctx);
|
|
302
|
+
if(!self->ec_group) {
|
|
303
|
+
EC_GROUP_free(self->ec_group);
|
|
304
|
+
PyErr_SetString(PyECErrorObject, "could not initialize ec group.");
|
|
305
|
+
BN_free(p);
|
|
306
|
+
BN_free(a);
|
|
307
|
+
BN_free(b);
|
|
308
|
+
return -1;
|
|
309
|
+
}
|
|
310
|
+
BN_free(p);
|
|
311
|
+
BN_free(a);
|
|
312
|
+
BN_free(b);
|
|
313
|
+
debug("Now, we're finished.\n");
|
|
314
|
+
}
|
|
315
|
+
// check if builtin curve specified.
|
|
316
|
+
else if(nid > 0 && !pObj && !aObj && !bObj && !params && !param_string) {
|
|
317
|
+
debug("nid => %d == %s...\n", nid, OBJ_nid2sn(nid));
|
|
318
|
+
self->ec_group = EC_GROUP_new_by_curve_name(nid);
|
|
319
|
+
if(self->ec_group == NULL) {
|
|
320
|
+
EC_GROUP_free(self->ec_group);
|
|
321
|
+
printf("could not find curve: error code = %s.", OBJ_nid2sn(nid));
|
|
322
|
+
PyErr_SetString(PyECErrorObject, "can't find specified curve.");
|
|
323
|
+
return -1;
|
|
324
|
+
}
|
|
325
|
+
#ifdef DEBUG
|
|
326
|
+
printf("OK!\n");
|
|
327
|
+
#endif
|
|
328
|
+
debug("ec group check...\n");
|
|
329
|
+
if(!EC_GROUP_check(self->ec_group, self->ctx)) {
|
|
330
|
+
EC_GROUP_free(self->ec_group);
|
|
331
|
+
PyErr_SetString(PyECErrorObject, "group check failed, try another curve.");
|
|
332
|
+
return -1;
|
|
333
|
+
}
|
|
334
|
+
self->nid = nid;
|
|
335
|
+
#ifdef DEBUG
|
|
336
|
+
printf("OK!\n");
|
|
337
|
+
#endif
|
|
338
|
+
}
|
|
339
|
+
else {
|
|
340
|
+
PyErr_SetString(PyECErrorObject, "invalid input. try again.");
|
|
341
|
+
return -1;
|
|
342
|
+
}
|
|
343
|
+
|
|
344
|
+
// obtain the order of the elliptic curve and store in group object
|
|
345
|
+
EC_GROUP_get_order(self->ec_group, self->order, self->ctx);
|
|
346
|
+
self->group_init = TRUE;
|
|
347
|
+
return 0;
|
|
348
|
+
}
|
|
349
|
+
|
|
350
|
+
PyObject *ECElement_call(ECElement *intObject, PyObject *args, PyObject *kwds) {
|
|
351
|
+
|
|
352
|
+
return NULL;
|
|
353
|
+
}
|
|
354
|
+
|
|
355
|
+
PyObject *ECGroup_print(ECGroup *self) {
|
|
356
|
+
if(!self->group_init)
|
|
357
|
+
return PyUnicode_FromString("");
|
|
358
|
+
BIGNUM *p = BN_new(), *a = BN_new(), *b = BN_new();
|
|
359
|
+
EC_GROUP_get_curve_GFp(self->ec_group, p, a, b, self->ctx);
|
|
360
|
+
|
|
361
|
+
const char *id;
|
|
362
|
+
if(self->nid == -1) id = "custom";
|
|
363
|
+
else id = OBJ_nid2sn(self->nid);
|
|
364
|
+
char *pstr = BN_bn2dec(p);
|
|
365
|
+
char *astr = BN_bn2dec(a);
|
|
366
|
+
char *bstr = BN_bn2dec(b);
|
|
367
|
+
PyObject *strObj = PyUnicode_FromFormat("Curve '%s' => y^2 = x^3 + a*x + b (mod p):\np = %s\na = %s\nb = %s", id, (const char *) pstr,
|
|
368
|
+
(const char *) astr, (const char *) bstr);
|
|
369
|
+
OPENSSL_free(pstr);
|
|
370
|
+
OPENSSL_free(astr);
|
|
371
|
+
OPENSSL_free(bstr);
|
|
372
|
+
BN_free(p);
|
|
373
|
+
BN_free(a);
|
|
374
|
+
BN_free(b);
|
|
375
|
+
return strObj;
|
|
376
|
+
}
|
|
377
|
+
|
|
378
|
+
PyObject *ECElement_print(ECElement *self) {
|
|
379
|
+
if(self->type == ZR) {
|
|
380
|
+
if(!self->point_init)
|
|
381
|
+
return PyUnicode_FromString("");
|
|
382
|
+
char *Zstr = BN_bn2dec(self->elemZ);
|
|
383
|
+
PyObject *strObj = PyUnicode_FromString((const char *) Zstr);
|
|
384
|
+
OPENSSL_free(Zstr);
|
|
385
|
+
return strObj;
|
|
386
|
+
}
|
|
387
|
+
else if(self->type == G) {
|
|
388
|
+
if(!self->point_init)
|
|
389
|
+
return PyUnicode_FromString("");
|
|
390
|
+
VERIFY_GROUP(self->group);
|
|
391
|
+
|
|
392
|
+
BIGNUM *x = BN_new(), *y = BN_new();
|
|
393
|
+
EC_POINT_get_affine_coordinates_GFp(self->group->ec_group, self->P, x, y, self->group->ctx);
|
|
394
|
+
char *xstr = BN_bn2dec(x);
|
|
395
|
+
char *ystr = BN_bn2dec(y);
|
|
396
|
+
//debug("P -> x = %s\n", xstr);
|
|
397
|
+
//debug("P -> y = %s\n", ystr);
|
|
398
|
+
PyObject *strObj = PyUnicode_FromFormat("[%s, %s]", (const char *)xstr, (const char *)ystr);
|
|
399
|
+
OPENSSL_free(xstr);
|
|
400
|
+
OPENSSL_free(ystr);
|
|
401
|
+
BN_free(x);
|
|
402
|
+
BN_free(y);
|
|
403
|
+
return strObj;
|
|
404
|
+
}
|
|
405
|
+
|
|
406
|
+
return (PyObject *) PyUnicode_FromString("");
|
|
407
|
+
}
|
|
408
|
+
|
|
409
|
+
PyObject *ECE_init(ECElement *self, PyObject *args) {
|
|
410
|
+
GroupType type = NONE_G;
|
|
411
|
+
ECElement *obj;
|
|
412
|
+
ECGroup *gobj = NULL;
|
|
413
|
+
PyObject *long_obj = NULL;
|
|
414
|
+
|
|
415
|
+
if(PyArg_ParseTuple(args, "Oi|O", &gobj, &type, &long_obj)) {
|
|
416
|
+
VERIFY_GROUP(gobj);
|
|
417
|
+
|
|
418
|
+
if(type == G) {
|
|
419
|
+
debug("init element in group G.\n");
|
|
420
|
+
obj = createNewPoint(G, gobj);
|
|
421
|
+
return (PyObject *) obj;
|
|
422
|
+
}
|
|
423
|
+
else if(type == ZR) {
|
|
424
|
+
debug("init element of ZR.\n");
|
|
425
|
+
obj = createNewPoint(ZR, gobj);
|
|
426
|
+
if(long_obj != NULL) {
|
|
427
|
+
if (_PyLong_Check(long_obj)) {
|
|
428
|
+
setBigNum((PyLongObject *) long_obj, &obj->elemZ);
|
|
429
|
+
BN_mod(obj->elemZ, obj->elemZ, gobj->order, gobj->ctx);
|
|
430
|
+
} else {
|
|
431
|
+
EXIT_IF(TRUE, "expecting a number (int or long)");
|
|
432
|
+
}
|
|
433
|
+
}
|
|
434
|
+
return (PyObject *) obj;
|
|
435
|
+
}
|
|
436
|
+
else {
|
|
437
|
+
EXIT_IF(TRUE, "invalid type selected.");
|
|
438
|
+
}
|
|
439
|
+
}
|
|
440
|
+
EXIT_IF(TRUE, "invalid argument.");
|
|
441
|
+
}
|
|
442
|
+
|
|
443
|
+
PyObject *ECE_random(ECElement *self, PyObject *args)
|
|
444
|
+
{
|
|
445
|
+
GroupType type = NONE_G;
|
|
446
|
+
ECGroup *gobj = NULL;
|
|
447
|
+
|
|
448
|
+
if(PyArg_ParseTuple(args, "Oi", &gobj, &type)) {
|
|
449
|
+
VERIFY_GROUP(gobj);
|
|
450
|
+
|
|
451
|
+
if(type == G) {
|
|
452
|
+
// generate a random element from ec group G.
|
|
453
|
+
// call 'EC_POINT_set_compressed_coordinates_GFp' w/ group, P, x, 1, ctx
|
|
454
|
+
// call 'EC_POINT_set_affine_coordinates_GFp' w/ group, P, x/y, ctx
|
|
455
|
+
// test group membership 'EC_POINT_is_on_curve'
|
|
456
|
+
ECElement *objG = createNewPoint(G, gobj);
|
|
457
|
+
BIGNUM *x = BN_new(), *y = BN_new(); // *order = BN_new();
|
|
458
|
+
//EC_GROUP_get_order(gobj->ec_group, order, gobj->ctx);
|
|
459
|
+
int FindAnotherPoint = TRUE;
|
|
460
|
+
//START_CLOCK(dBench);
|
|
461
|
+
do {
|
|
462
|
+
// generate random point
|
|
463
|
+
BN_rand_range(x, gobj->order);
|
|
464
|
+
EC_POINT_set_compressed_coordinates_GFp(gobj->ec_group, objG->P, x, 1, gobj->ctx);
|
|
465
|
+
EC_POINT_get_affine_coordinates_GFp(gobj->ec_group, objG->P, x, y, gobj->ctx);
|
|
466
|
+
// make sure point is on curve and not zero
|
|
467
|
+
|
|
468
|
+
if(BN_is_zero(x) || BN_is_zero(y)) {
|
|
469
|
+
FindAnotherPoint = TRUE;
|
|
470
|
+
continue;
|
|
471
|
+
}
|
|
472
|
+
|
|
473
|
+
if(EC_POINT_is_on_curve(gobj->ec_group, objG->P, gobj->ctx)) {
|
|
474
|
+
FindAnotherPoint = FALSE;
|
|
475
|
+
}
|
|
476
|
+
// char *xstr = BN_bn2dec(x);
|
|
477
|
+
// char *ystr = BN_bn2dec(y);
|
|
478
|
+
// debug("P -> x = %s\n", xstr);
|
|
479
|
+
// debug("P -> y = %s\n", ystr);
|
|
480
|
+
// OPENSSL_free(xstr);
|
|
481
|
+
// OPENSSL_free(ystr);
|
|
482
|
+
} while(FindAnotherPoint);
|
|
483
|
+
|
|
484
|
+
BN_free(x);
|
|
485
|
+
BN_free(y);
|
|
486
|
+
// BN_free(order);
|
|
487
|
+
return (PyObject *) objG;
|
|
488
|
+
}
|
|
489
|
+
else if(type == ZR) {
|
|
490
|
+
ECElement *objZR = createNewPoint(ZR, gobj);
|
|
491
|
+
BN_rand_range(objZR->elemZ, gobj->order);
|
|
492
|
+
|
|
493
|
+
return (PyObject *) objZR;
|
|
494
|
+
}
|
|
495
|
+
else {
|
|
496
|
+
|
|
497
|
+
EXIT_IF(TRUE, "invalid object type.");
|
|
498
|
+
}
|
|
499
|
+
}
|
|
500
|
+
|
|
501
|
+
|
|
502
|
+
EXIT_IF(TRUE, "invalid argument.");
|
|
503
|
+
}
|
|
504
|
+
|
|
505
|
+
static PyObject *ECE_is_infinity(ECElement *self, PyObject *args) {
|
|
506
|
+
|
|
507
|
+
Point_Init(self);
|
|
508
|
+
EXIT_IF(self->type != G, "element not of type G.");
|
|
509
|
+
|
|
510
|
+
if(EC_POINT_is_at_infinity(self->group->ec_group, self->P)) {
|
|
511
|
+
Py_INCREF(Py_True);
|
|
512
|
+
return Py_True;
|
|
513
|
+
}
|
|
514
|
+
|
|
515
|
+
Py_INCREF(Py_False);
|
|
516
|
+
return Py_False;
|
|
517
|
+
}
|
|
518
|
+
|
|
519
|
+
static PyObject *ECE_add(PyObject *o1, PyObject *o2) {
|
|
520
|
+
ECElement *lhs = NULL, *rhs = NULL, *ans = NULL;
|
|
521
|
+
int foundLHS = FALSE, foundRHS = FALSE;
|
|
522
|
+
|
|
523
|
+
Check_Types2(o1, o2, lhs, rhs, foundLHS, foundRHS);
|
|
524
|
+
|
|
525
|
+
if(foundLHS) {
|
|
526
|
+
debug("found lhs.\n");
|
|
527
|
+
// if rhs == ZR, then convert lhs to a bn otherwise fail.
|
|
528
|
+
if(rhs->point_init && rhs->type == ZR) {
|
|
529
|
+
BIGNUM *lhs_val = BN_new();
|
|
530
|
+
setBigNum((PyLongObject *) o1, &lhs_val);
|
|
531
|
+
ans = createNewPoint(ZR, rhs->group);
|
|
532
|
+
BN_mod_add(ans->elemZ, lhs_val, rhs->elemZ, ans->group->order, ans->group->ctx);
|
|
533
|
+
BN_free(lhs_val);
|
|
534
|
+
#ifdef BENCHMARK_ENABLED
|
|
535
|
+
UPDATE_BENCH(ADDITION, ans->type, ans->group);
|
|
536
|
+
#endif
|
|
537
|
+
return (PyObject *) ans;
|
|
538
|
+
}
|
|
539
|
+
}
|
|
540
|
+
else if(foundRHS) {
|
|
541
|
+
debug("found rhs.\n");
|
|
542
|
+
// if lhs == ZR, then convert rhs to a bn otherwise fail.
|
|
543
|
+
if(lhs->point_init && lhs->type == ZR) {
|
|
544
|
+
BIGNUM *rhs_val = BN_new();
|
|
545
|
+
setBigNum((PyLongObject *) o2, &rhs_val);
|
|
546
|
+
ans = createNewPoint(ZR, lhs->group); // ->group, lhs->ctx);
|
|
547
|
+
BN_mod_add(ans->elemZ, lhs->elemZ, rhs_val, ans->group->order, ans->group->ctx);
|
|
548
|
+
BN_free(rhs_val);
|
|
549
|
+
#ifdef BENCHMARK_ENABLED
|
|
550
|
+
UPDATE_BENCH(ADDITION, ans->type, ans->group);
|
|
551
|
+
#endif
|
|
552
|
+
return (PyObject *) ans;
|
|
553
|
+
}
|
|
554
|
+
}
|
|
555
|
+
else {
|
|
556
|
+
// check whether we have two Points
|
|
557
|
+
Point_Init(lhs);
|
|
558
|
+
Point_Init(rhs);
|
|
559
|
+
if(ElementZR(lhs, rhs)) {
|
|
560
|
+
|
|
561
|
+
IS_SAME_GROUP(lhs, rhs);
|
|
562
|
+
// easy, just call BN_add
|
|
563
|
+
ans = createNewPoint(ZR, lhs->group);
|
|
564
|
+
BN_mod_add(ans->elemZ, lhs->elemZ, rhs->elemZ, ans->group->order, ans->group->ctx);
|
|
565
|
+
#ifdef BENCHMARK_ENABLED
|
|
566
|
+
UPDATE_BENCH(ADDITION, ans->type, ans->group);
|
|
567
|
+
#endif
|
|
568
|
+
return (PyObject *) ans;
|
|
569
|
+
}
|
|
570
|
+
else { // if(lhs->type == G && rhs->type == ZR) or vice versa operation undefined...
|
|
571
|
+
|
|
572
|
+
EXIT_IF(TRUE, "adding the a group element G to ZR is undefined.");
|
|
573
|
+
}
|
|
574
|
+
}
|
|
575
|
+
|
|
576
|
+
EXIT_IF(TRUE, "invalid arguments.");
|
|
577
|
+
}
|
|
578
|
+
|
|
579
|
+
/*
|
|
580
|
+
* Point Subtraction of two points A and B is really
|
|
581
|
+
* A + (-B) where -B is the reflection of that point with
|
|
582
|
+
* respect to the x-axis. i.e. (xb,yb) => (xb,-yb)
|
|
583
|
+
*/
|
|
584
|
+
static PyObject *ECE_sub(PyObject *o1, PyObject *o2) {
|
|
585
|
+
ECElement *lhs = NULL, *rhs = NULL, *ans = NULL;
|
|
586
|
+
int foundLHS = FALSE, foundRHS = FALSE;
|
|
587
|
+
|
|
588
|
+
Check_Types2(o1, o2, lhs, rhs, foundLHS, foundRHS);
|
|
589
|
+
|
|
590
|
+
if(foundLHS) {
|
|
591
|
+
debug("found lhs.\n");
|
|
592
|
+
// if rhs == ZR, then convert lhs to a bn otherwise fail.
|
|
593
|
+
// only supported for elements of Long (lhs) and ZR (rhs)
|
|
594
|
+
if(rhs->point_init && rhs->type == ZR) {
|
|
595
|
+
BIGNUM *lhs_val = BN_new();
|
|
596
|
+
setBigNum((PyLongObject *) o1, &lhs_val);
|
|
597
|
+
ans = createNewPoint(ZR, rhs->group); // ->group, rhs->ctx);
|
|
598
|
+
BN_mod_sub(ans->elemZ, lhs_val, rhs->elemZ, ans->group->order, ans->group->ctx);
|
|
599
|
+
BN_free(lhs_val);
|
|
600
|
+
#ifdef BENCHMARK_ENABLED
|
|
601
|
+
UPDATE_BENCH(SUBTRACTION, ans->type, ans->group);
|
|
602
|
+
#endif
|
|
603
|
+
return (PyObject *) ans;
|
|
604
|
+
}
|
|
605
|
+
}
|
|
606
|
+
else if(foundRHS) {
|
|
607
|
+
debug("found rhs.\n");
|
|
608
|
+
// if lhs == ZR, then convert rhs to a bn otherwise fail.
|
|
609
|
+
// only supported for elements of ZR (lhs) and Long (rhs)
|
|
610
|
+
if(lhs->point_init && lhs->type == ZR) {
|
|
611
|
+
BIGNUM *rhs_val = BN_new();
|
|
612
|
+
setBigNum((PyLongObject *) o2, &rhs_val);
|
|
613
|
+
ans = createNewPoint(ZR, lhs->group);
|
|
614
|
+
BN_mod_sub(ans->elemZ, lhs->elemZ, rhs_val, ans->group->order, ans->group->ctx);
|
|
615
|
+
BN_free(rhs_val);
|
|
616
|
+
#ifdef BENCHMARK_ENABLED
|
|
617
|
+
UPDATE_BENCH(SUBTRACTION, ans->type, ans->group);
|
|
618
|
+
#endif
|
|
619
|
+
return (PyObject *) ans;
|
|
620
|
+
}
|
|
621
|
+
}
|
|
622
|
+
else {
|
|
623
|
+
// check whether we have two Points
|
|
624
|
+
Point_Init(lhs);
|
|
625
|
+
Point_Init(rhs);
|
|
626
|
+
|
|
627
|
+
if(ElementZR(lhs, rhs)) {
|
|
628
|
+
IS_SAME_GROUP(lhs, rhs);
|
|
629
|
+
ans = createNewPoint(ZR, lhs->group);
|
|
630
|
+
BN_mod_sub(ans->elemZ, lhs->elemZ, rhs->elemZ, ans->group->order, ans->group->ctx);
|
|
631
|
+
#ifdef BENCHMARK_ENABLED
|
|
632
|
+
UPDATE_BENCH(SUBTRACTION, ans->type, ans->group);
|
|
633
|
+
#endif
|
|
634
|
+
return (PyObject *) ans;
|
|
635
|
+
}
|
|
636
|
+
else {
|
|
637
|
+
// not defined for other combinations
|
|
638
|
+
EXIT_IF(TRUE, "invalid combination of operands.");
|
|
639
|
+
}
|
|
640
|
+
}
|
|
641
|
+
|
|
642
|
+
|
|
643
|
+
EXIT_IF(TRUE, "invalid arguments.");
|
|
644
|
+
}
|
|
645
|
+
|
|
646
|
+
static PyObject *ECE_mul(PyObject *o1, PyObject *o2) {
|
|
647
|
+
ECElement *lhs = NULL, *rhs = NULL, *ans = NULL;
|
|
648
|
+
int foundLHS = FALSE, foundRHS = FALSE;
|
|
649
|
+
|
|
650
|
+
Check_Types2(o1, o2, lhs, rhs, foundLHS, foundRHS);
|
|
651
|
+
|
|
652
|
+
if(foundLHS) {
|
|
653
|
+
debug("found lhs.\n");
|
|
654
|
+
// if rhs == ZR, then convert lhs to a bn otherwise fail.
|
|
655
|
+
// only supported for elements of Long (lhs) and ZR (rhs)
|
|
656
|
+
if(rhs->point_init && rhs->type == ZR) {
|
|
657
|
+
BIGNUM *lhs_val = BN_new();
|
|
658
|
+
setBigNum((PyLongObject *) o1, &lhs_val);
|
|
659
|
+
ans = createNewPoint(ZR, rhs->group);
|
|
660
|
+
BN_mod_mul(ans->elemZ, lhs_val, rhs->elemZ, ans->group->order, ans->group->ctx);
|
|
661
|
+
BN_free(lhs_val);
|
|
662
|
+
#ifdef BENCHMARK_ENABLED
|
|
663
|
+
UPDATE_BENCH(MULTIPLICATION, ans->type, ans->group);
|
|
664
|
+
#endif
|
|
665
|
+
return (PyObject *) ans;
|
|
666
|
+
}
|
|
667
|
+
}
|
|
668
|
+
else if(foundRHS) {
|
|
669
|
+
debug("found rhs.\n");
|
|
670
|
+
// if lhs == ZR, then convert rhs to a bn otherwise fail.
|
|
671
|
+
// only supported for elements of ZR (lhs) and Long (rhs)
|
|
672
|
+
if(lhs->point_init && lhs->type == ZR) {
|
|
673
|
+
BIGNUM *rhs_val = BN_new();
|
|
674
|
+
setBigNum((PyLongObject *) o2, &rhs_val);
|
|
675
|
+
ans = createNewPoint(ZR, lhs->group); // ->group, lhs->ctx);
|
|
676
|
+
BN_mod_mul(ans->elemZ, lhs->elemZ, rhs_val, ans->group->order, ans->group->ctx);
|
|
677
|
+
BN_free(rhs_val);
|
|
678
|
+
#ifdef BENCHMARK_ENABLED
|
|
679
|
+
UPDATE_BENCH(MULTIPLICATION, ans->type, ans->group);
|
|
680
|
+
#endif
|
|
681
|
+
return (PyObject *) ans;
|
|
682
|
+
}
|
|
683
|
+
}
|
|
684
|
+
else {
|
|
685
|
+
// check whether we have two Points
|
|
686
|
+
Point_Init(lhs);
|
|
687
|
+
Point_Init(rhs);
|
|
688
|
+
IS_SAME_GROUP(lhs, rhs);
|
|
689
|
+
|
|
690
|
+
if(ElementG(lhs, rhs)) {
|
|
691
|
+
ans = createNewPoint(G, lhs->group);
|
|
692
|
+
EC_POINT_add(ans->group->ec_group, ans->P, lhs->P, rhs->P, ans->group->ctx);
|
|
693
|
+
}
|
|
694
|
+
else if(ElementZR(lhs, rhs)) {
|
|
695
|
+
ans = createNewPoint(ZR, lhs->group);
|
|
696
|
+
BN_mod_mul(ans->elemZ, lhs->elemZ, rhs->elemZ, ans->group->order, ans->group->ctx);
|
|
697
|
+
}
|
|
698
|
+
else {
|
|
699
|
+
|
|
700
|
+
EXIT_IF(TRUE, "elements are not of the same type.");
|
|
701
|
+
}
|
|
702
|
+
#ifdef BENCHMARK_ENABLED
|
|
703
|
+
UPDATE_BENCH(MULTIPLICATION, ans->type, ans->group);
|
|
704
|
+
#endif
|
|
705
|
+
return (PyObject *) ans;
|
|
706
|
+
}
|
|
707
|
+
|
|
708
|
+
|
|
709
|
+
ErrorMsg("invalid argument.");
|
|
710
|
+
}
|
|
711
|
+
|
|
712
|
+
static PyObject *ECE_div(PyObject *o1, PyObject *o2) {
|
|
713
|
+
;
|
|
714
|
+
ECElement *lhs = NULL, *rhs = NULL, *ans = NULL;
|
|
715
|
+
BIGNUM *rm = NULL;
|
|
716
|
+
int foundLHS = FALSE, foundRHS = FALSE;
|
|
717
|
+
|
|
718
|
+
Check_Types2(o1, o2, lhs, rhs, foundLHS, foundRHS);
|
|
719
|
+
|
|
720
|
+
if(foundLHS) {
|
|
721
|
+
debug("found lhs.\n");
|
|
722
|
+
// if rhs == ZR, then convert lhs to a bn otherwise fail.
|
|
723
|
+
// only supported for elements of Long (lhs) and ZR (rhs)
|
|
724
|
+
if(rhs->point_init && rhs->type == ZR) {
|
|
725
|
+
BIGNUM *lhs_val = BN_new();
|
|
726
|
+
rm = BN_new();
|
|
727
|
+
setBigNum((PyLongObject *) o1, &lhs_val);
|
|
728
|
+
ans = createNewPoint(ZR, rhs->group);
|
|
729
|
+
BN_div(ans->elemZ, rm, lhs_val, rhs->elemZ, ans->group->ctx);
|
|
730
|
+
BN_free(lhs_val);
|
|
731
|
+
BN_free(rm);
|
|
732
|
+
#ifdef BENCHMARK_ENABLED
|
|
733
|
+
UPDATE_BENCH(DIVISION, ans->type, ans->group);
|
|
734
|
+
#endif
|
|
735
|
+
return (PyObject *) ans;
|
|
736
|
+
}
|
|
737
|
+
}
|
|
738
|
+
else if(foundRHS) {
|
|
739
|
+
debug("found rhs.\n");
|
|
740
|
+
// if lhs == ZR, then convert rhs to a bn otherwise fail.
|
|
741
|
+
// only supported for elements of ZR (lhs) and Long (rhs)
|
|
742
|
+
if(lhs->point_init && lhs->type == ZR) {
|
|
743
|
+
BIGNUM *rhs_val = BN_new();
|
|
744
|
+
rm = BN_new();
|
|
745
|
+
setBigNum((PyLongObject *) o2, &rhs_val);
|
|
746
|
+
ans = createNewPoint(ZR, lhs->group); // ->group, lhs->ctx);
|
|
747
|
+
BN_div(ans->elemZ, rm, lhs->elemZ, rhs_val, ans->group->ctx);
|
|
748
|
+
BN_free(rhs_val);
|
|
749
|
+
BN_free(rm);
|
|
750
|
+
#ifdef BENCHMARK_ENABLED
|
|
751
|
+
UPDATE_BENCH(DIVISION, ans->type, ans->group);
|
|
752
|
+
#endif
|
|
753
|
+
return (PyObject *) ans;
|
|
754
|
+
}
|
|
755
|
+
}
|
|
756
|
+
else {
|
|
757
|
+
// check whether we have two Points
|
|
758
|
+
Point_Init(lhs);
|
|
759
|
+
Point_Init(rhs);
|
|
760
|
+
IS_SAME_GROUP(lhs, rhs);
|
|
761
|
+
|
|
762
|
+
if(ElementG(lhs, rhs)) {
|
|
763
|
+
ECElement *rhs_neg = negatePoint(rhs);
|
|
764
|
+
if(rhs_neg != NULL) {
|
|
765
|
+
ans = createNewPoint(G, lhs->group);
|
|
766
|
+
EC_POINT_add(ans->group->ec_group, ans->P, lhs->P, rhs_neg->P, ans->group->ctx);
|
|
767
|
+
}
|
|
768
|
+
Py_DECREF(rhs_neg);
|
|
769
|
+
}
|
|
770
|
+
else if(ElementZR(lhs, rhs)) {
|
|
771
|
+
ans = createNewPoint(ZR, lhs->group);
|
|
772
|
+
rm = BN_new();
|
|
773
|
+
BN_div(ans->elemZ, rm, lhs->elemZ, rhs->elemZ, ans->group->ctx);
|
|
774
|
+
BN_free(rm);
|
|
775
|
+
}
|
|
776
|
+
else {
|
|
777
|
+
|
|
778
|
+
EXIT_IF(TRUE, "elements not the same type.");
|
|
779
|
+
}
|
|
780
|
+
#ifdef BENCHMARK_ENABLED
|
|
781
|
+
UPDATE_BENCH(DIVISION, ans->type, ans->group);
|
|
782
|
+
#endif
|
|
783
|
+
return (PyObject *) ans;
|
|
784
|
+
}
|
|
785
|
+
|
|
786
|
+
EXIT_IF(TRUE, "invalid argument.");
|
|
787
|
+
}
|
|
788
|
+
|
|
789
|
+
static PyObject *ECE_rem(PyObject *o1, PyObject *o2) {
|
|
790
|
+
;
|
|
791
|
+
ECElement *lhs = NULL, *rhs = NULL, *ans = NULL;
|
|
792
|
+
int foundLHS = FALSE, foundRHS = FALSE;
|
|
793
|
+
|
|
794
|
+
Check_Types2(o1, o2, lhs, rhs, foundLHS, foundRHS);
|
|
795
|
+
|
|
796
|
+
if(foundLHS) {
|
|
797
|
+
debug("found lhs.\n");
|
|
798
|
+
// if rhs == ZR, then convert lhs to a bn otherwise fail.
|
|
799
|
+
// only supported for elements of Long (lhs) and ZR (rhs)
|
|
800
|
+
if(rhs->point_init && rhs->type == ZR) {
|
|
801
|
+
BIGNUM *lhs_val = BN_new();
|
|
802
|
+
setBigNum((PyLongObject *) o1, &lhs_val);
|
|
803
|
+
ans = createNewPoint(ZR, rhs->group);
|
|
804
|
+
BN_mod(ans->elemZ, lhs_val, rhs->elemZ, ans->group->ctx);
|
|
805
|
+
BN_free(lhs_val);
|
|
806
|
+
|
|
807
|
+
return (PyObject *) ans;
|
|
808
|
+
}
|
|
809
|
+
}
|
|
810
|
+
else if(foundRHS) {
|
|
811
|
+
debug("found rhs.\n");
|
|
812
|
+
// if lhs == ZR, then convert rhs to a bn otherwise fail.
|
|
813
|
+
// only supported for elements of ZR (lhs) and Long (rhs)
|
|
814
|
+
if(lhs->point_init && lhs->type == ZR) {
|
|
815
|
+
BIGNUM *rhs_val = BN_new();
|
|
816
|
+
setBigNum((PyLongObject *) o2, &rhs_val);
|
|
817
|
+
ans = createNewPoint(ZR, lhs->group);
|
|
818
|
+
BN_mod(ans->elemZ, lhs->elemZ, rhs_val, ans->group->ctx);
|
|
819
|
+
BN_free(rhs_val);
|
|
820
|
+
return (PyObject *) ans;
|
|
821
|
+
}
|
|
822
|
+
}
|
|
823
|
+
else {
|
|
824
|
+
Point_Init(lhs);
|
|
825
|
+
Point_Init(rhs);
|
|
826
|
+
|
|
827
|
+
if(ElementZR(lhs, rhs)) {
|
|
828
|
+
ans = createNewPoint(ZR, lhs->group);
|
|
829
|
+
// reall calls BN_div with the dv se to NULL.
|
|
830
|
+
BN_mod(ans->elemZ, lhs->elemZ, rhs->elemZ, ans->group->ctx);
|
|
831
|
+
return (PyObject *) ans;
|
|
832
|
+
}
|
|
833
|
+
else {
|
|
834
|
+
|
|
835
|
+
EXIT_IF(TRUE, "invalid combination of element types");
|
|
836
|
+
}
|
|
837
|
+
}
|
|
838
|
+
|
|
839
|
+
|
|
840
|
+
EXIT_IF(TRUE, "invalid argument type.");
|
|
841
|
+
}
|
|
842
|
+
|
|
843
|
+
static PyObject *ECE_pow(PyObject *o1, PyObject *o2, PyObject *o3) {
|
|
844
|
+
ECElement *lhs = NULL, *rhs = NULL, *ans = NULL;
|
|
845
|
+
int foundLHS = FALSE, foundRHS = FALSE;
|
|
846
|
+
|
|
847
|
+
Check_Types2(o1, o2, lhs, rhs, foundLHS, foundRHS);
|
|
848
|
+
|
|
849
|
+
if(foundLHS) {
|
|
850
|
+
// TODO: implement for elements of Long ** ZR
|
|
851
|
+
if(rhs->point_init && rhs->type == ZR) {
|
|
852
|
+
BIGNUM *lhs_val = BN_new();
|
|
853
|
+
setBigNum((PyLongObject *) o1, &lhs_val);
|
|
854
|
+
ans = createNewPoint(ZR, rhs->group);
|
|
855
|
+
BN_mod_exp(ans->elemZ, lhs_val, rhs->elemZ, ans->group->order, ans->group->ctx);
|
|
856
|
+
BN_free(lhs_val);
|
|
857
|
+
#ifdef BENCHMARK_ENABLED
|
|
858
|
+
UPDATE_BENCH(EXPONENTIATION, ans->type, ans->group);
|
|
859
|
+
#endif
|
|
860
|
+
return (PyObject *) ans;
|
|
861
|
+
}
|
|
862
|
+
EXIT_IF(TRUE, "element type combination not supported.");
|
|
863
|
+
}
|
|
864
|
+
else if(foundRHS) {
|
|
865
|
+
// TODO: implement for elements of G ** Long or ZR ** Long
|
|
866
|
+
long rhs = PyLong_AsLong(o2);
|
|
867
|
+
if(lhs->type == ZR) {
|
|
868
|
+
if(PyErr_Occurred() || rhs >= 0) {
|
|
869
|
+
// clear error and continue
|
|
870
|
+
// PyErr_Print(); // for debug purposes
|
|
871
|
+
PyErr_Clear();
|
|
872
|
+
BIGNUM *rhs_val = BN_new();
|
|
873
|
+
setBigNum((PyLongObject *) o2, &rhs_val);
|
|
874
|
+
|
|
875
|
+
ans = createNewPoint(ZR, lhs->group);
|
|
876
|
+
BN_mod_exp(ans->elemZ, lhs->elemZ, rhs_val, ans->group->order, ans->group->ctx);
|
|
877
|
+
BN_free(rhs_val);
|
|
878
|
+
}
|
|
879
|
+
else if(rhs == -1) {
|
|
880
|
+
debug("finding modular inverse.\n");
|
|
881
|
+
ans = invertECElement(lhs);
|
|
882
|
+
}
|
|
883
|
+
else {
|
|
884
|
+
EXIT_IF(TRUE, "unsupported operation.");
|
|
885
|
+
}
|
|
886
|
+
}
|
|
887
|
+
else if(lhs->type == G) {
|
|
888
|
+
if(PyErr_Occurred() || rhs >= 0) {
|
|
889
|
+
// clear error and continue
|
|
890
|
+
// PyErr_Print(); // for debug purposes
|
|
891
|
+
PyErr_Clear();
|
|
892
|
+
BIGNUM *rhs_val = BN_new();
|
|
893
|
+
setBigNum((PyLongObject *) o2, &rhs_val);
|
|
894
|
+
ans = createNewPoint(G, lhs->group); // ->group, lhs->ctx);
|
|
895
|
+
EC_POINT_mul(ans->group->ec_group, ans->P, NULL, lhs->P, rhs_val, ans->group->ctx);
|
|
896
|
+
BN_free(rhs_val);
|
|
897
|
+
}
|
|
898
|
+
else if(rhs == -1) {
|
|
899
|
+
debug("finding modular inverse.\n");
|
|
900
|
+
ans = invertECElement(lhs);
|
|
901
|
+
}
|
|
902
|
+
else {
|
|
903
|
+
EXIT_IF(TRUE, "unsupported operation.");
|
|
904
|
+
}
|
|
905
|
+
}
|
|
906
|
+
else {
|
|
907
|
+
EXIT_IF(TRUE, "element type combination not supported.");
|
|
908
|
+
}
|
|
909
|
+
#ifdef BENCHMARK_ENABLED
|
|
910
|
+
UPDATE_BENCH(EXPONENTIATION, ans->type, ans->group);
|
|
911
|
+
#endif
|
|
912
|
+
return (PyObject *) ans;
|
|
913
|
+
}
|
|
914
|
+
else {
|
|
915
|
+
// check whether we have two Points
|
|
916
|
+
Point_Init(lhs);
|
|
917
|
+
Point_Init(rhs);
|
|
918
|
+
IS_SAME_GROUP(lhs, rhs);
|
|
919
|
+
|
|
920
|
+
if(lhs->type == G && rhs->type == ZR) {
|
|
921
|
+
ans = createNewPoint(G, lhs->group);
|
|
922
|
+
EC_POINT_mul(ans->group->ec_group, ans->P, NULL, lhs->P, rhs->elemZ, ans->group->ctx);
|
|
923
|
+
}
|
|
924
|
+
else if(ElementZR(lhs, rhs)) {
|
|
925
|
+
ans = createNewPoint(ZR, lhs->group);
|
|
926
|
+
BN_mod_exp(ans->elemZ, lhs->elemZ, rhs->elemZ, ans->group->order, ans->group->ctx);
|
|
927
|
+
}
|
|
928
|
+
else {
|
|
929
|
+
|
|
930
|
+
EXIT_IF(TRUE, "cannot exponentiate two points.");
|
|
931
|
+
}
|
|
932
|
+
#if BENCHMARK_ENABLED
|
|
933
|
+
UPDATE_BENCH(EXPONENTIATION, ans->type, ans->group);
|
|
934
|
+
#endif
|
|
935
|
+
return (PyObject *) ans;
|
|
936
|
+
}
|
|
937
|
+
|
|
938
|
+
EXIT_IF(TRUE, "invalid arguments.");
|
|
939
|
+
}
|
|
940
|
+
|
|
941
|
+
/* assume 'self' is a valid ECElement instance */
|
|
942
|
+
ECElement *invertECElement(ECElement *self) {
|
|
943
|
+
ECElement *newObj = NULL;
|
|
944
|
+
if(self->type == G) {
|
|
945
|
+
newObj = createNewPoint(G, self->group); // ->group, self->ctx);
|
|
946
|
+
EC_POINT_copy(newObj->P, self->P);
|
|
947
|
+
if(EC_POINT_invert(newObj->group->ec_group, newObj->P, newObj->group->ctx)) {
|
|
948
|
+
return newObj;
|
|
949
|
+
}
|
|
950
|
+
Py_XDECREF(newObj);
|
|
951
|
+
}
|
|
952
|
+
else if(self->type == ZR) {
|
|
953
|
+
// get modulus and compute mod_inverse
|
|
954
|
+
BIGNUM *x = BN_mod_inverse(NULL, self->elemZ, self->group->order, self->group->ctx);
|
|
955
|
+
if(x != NULL) {
|
|
956
|
+
newObj = createNewPoint(ZR, self->group);
|
|
957
|
+
BN_copy(newObj->elemZ, x);
|
|
958
|
+
BN_free(x);
|
|
959
|
+
return newObj;
|
|
960
|
+
}
|
|
961
|
+
Py_XDECREF(newObj);
|
|
962
|
+
}
|
|
963
|
+
/* error */
|
|
964
|
+
return NULL;
|
|
965
|
+
}
|
|
966
|
+
|
|
967
|
+
static PyObject *ECE_invert(PyObject *o1) {
|
|
968
|
+
|
|
969
|
+
if(PyEC_Check(o1)) {
|
|
970
|
+
ECElement *obj1 = (ECElement *) o1;
|
|
971
|
+
Point_Init(obj1);
|
|
972
|
+
|
|
973
|
+
ECElement *obj2 = invertECElement(obj1);
|
|
974
|
+
|
|
975
|
+
if(obj2 != NULL) {
|
|
976
|
+
|
|
977
|
+
return (PyObject *) obj2;
|
|
978
|
+
}
|
|
979
|
+
|
|
980
|
+
EXIT_IF(TRUE, "could not find inverse of element.");
|
|
981
|
+
}
|
|
982
|
+
|
|
983
|
+
EXIT_IF(TRUE, "invalid argument type.");
|
|
984
|
+
}
|
|
985
|
+
|
|
986
|
+
/* assume 'self' is a valid ECElement instance */
|
|
987
|
+
ECElement *negatePoint(ECElement *self) {
|
|
988
|
+
ECElement *newObj = NULL;
|
|
989
|
+
|
|
990
|
+
BIGNUM *x = BN_new(), *y = BN_new();
|
|
991
|
+
EC_POINT_get_affine_coordinates_GFp(self->group->ec_group, self->P, x, y, self->group->ctx);
|
|
992
|
+
BN_set_negative(y, TRUE);
|
|
993
|
+
|
|
994
|
+
newObj = createNewPoint(G, self->group);
|
|
995
|
+
EC_POINT_set_affine_coordinates_GFp(newObj->group->ec_group, newObj->P, x, y, newObj->group->ctx);
|
|
996
|
+
BN_free(x);
|
|
997
|
+
BN_free(y);
|
|
998
|
+
if(EC_POINT_is_on_curve(newObj->group->ec_group, newObj->P, newObj->group->ctx)) {
|
|
999
|
+
return newObj;
|
|
1000
|
+
}
|
|
1001
|
+
/* error */
|
|
1002
|
+
Py_DECREF(newObj);
|
|
1003
|
+
return NULL;
|
|
1004
|
+
}
|
|
1005
|
+
|
|
1006
|
+
static PyObject *ECE_neg(PyObject *o1) {
|
|
1007
|
+
ECElement *obj1 = NULL, *obj2 = NULL;
|
|
1008
|
+
|
|
1009
|
+
if(PyEC_Check(o1)) {
|
|
1010
|
+
obj1 = (ECElement *) o1;
|
|
1011
|
+
Point_Init(obj1);
|
|
1012
|
+
|
|
1013
|
+
if(obj1->type == G) {
|
|
1014
|
+
if((obj2 = negatePoint(obj1)) != NULL) {
|
|
1015
|
+
return (PyObject *) obj2;
|
|
1016
|
+
}
|
|
1017
|
+
}
|
|
1018
|
+
else if(obj1->type == ZR) {
|
|
1019
|
+
// consider supporting this type.
|
|
1020
|
+
obj2 = createNewPoint(ZR, obj1->group);
|
|
1021
|
+
if(BN_copy(obj2->elemZ, obj1->elemZ) != NULL) {
|
|
1022
|
+
int negate;
|
|
1023
|
+
if(!BN_is_negative(obj2->elemZ)) negate = -1;
|
|
1024
|
+
else negate = 0;
|
|
1025
|
+
BN_set_negative(obj2->elemZ, negate);
|
|
1026
|
+
|
|
1027
|
+
return (PyObject *) obj2;
|
|
1028
|
+
}
|
|
1029
|
+
Py_XDECREF(obj2);
|
|
1030
|
+
}
|
|
1031
|
+
|
|
1032
|
+
}
|
|
1033
|
+
|
|
1034
|
+
|
|
1035
|
+
EXIT_IF(TRUE, "invalid argument.");
|
|
1036
|
+
}
|
|
1037
|
+
|
|
1038
|
+
static PyObject *ECE_long(PyObject *o1) {
|
|
1039
|
+
ECElement *obj1 = NULL;
|
|
1040
|
+
if(PyEC_Check(o1)) {
|
|
1041
|
+
obj1 = (ECElement *) o1;
|
|
1042
|
+
if(obj1->type == ZR) {
|
|
1043
|
+
/* borrowed from mixminion 0.0.7.1 */
|
|
1044
|
+
// now convert to python integer
|
|
1045
|
+
char *hex = BN_bn2hex(obj1->elemZ);
|
|
1046
|
+
PyObject *output = PyLong_FromString(hex, NULL, BASE_HEX);
|
|
1047
|
+
OPENSSL_free(hex);
|
|
1048
|
+
return output; /* pass along errors */
|
|
1049
|
+
}
|
|
1050
|
+
}
|
|
1051
|
+
EXIT_IF(TRUE, "cannot convert this type of object to an integer.");
|
|
1052
|
+
}
|
|
1053
|
+
|
|
1054
|
+
static PyObject *ECE_convertToZR(ECElement *self, PyObject *args) {
|
|
1055
|
+
ECElement *obj = NULL;
|
|
1056
|
+
ECGroup *gobj = NULL;
|
|
1057
|
+
PyObject *retXY = NULL;
|
|
1058
|
+
|
|
1059
|
+
/* gobj - initialized ec group object */
|
|
1060
|
+
/* obj - ecc point object on an elliptic curve */
|
|
1061
|
+
/* retXY => whether to return just x (Py_True) or x and y (Py_False) */
|
|
1062
|
+
if(PyArg_ParseTuple(args, "OOO", &gobj, &obj, &retXY)) {
|
|
1063
|
+
VERIFY_GROUP(gobj);
|
|
1064
|
+
|
|
1065
|
+
if(PyEC_Check(obj)) {
|
|
1066
|
+
// convert to
|
|
1067
|
+
Point_Init(obj);
|
|
1068
|
+
if(obj->type == G) {
|
|
1069
|
+
BIGNUM *x = BN_new(), *y = BN_new();
|
|
1070
|
+
EC_POINT_get_affine_coordinates_GFp(gobj->ec_group, obj->P, x, y, gobj->ctx);
|
|
1071
|
+
if(PyBool_Check(retXY)) {
|
|
1072
|
+
// see if retXY is Py_True or Py_False
|
|
1073
|
+
if(retXY == Py_True) {
|
|
1074
|
+
debug("Py_True detected.\n");
|
|
1075
|
+
ECElement *X = createNewPoint(ZR, gobj);
|
|
1076
|
+
ECElement *Y = createNewPoint(ZR, gobj);
|
|
1077
|
+
BN_copy(X->elemZ, x);
|
|
1078
|
+
BN_copy(Y->elemZ, y);
|
|
1079
|
+
BN_free(x); BN_free(y);
|
|
1080
|
+
return (PyObject *) PyTuple_Pack(2, (PyObject *) X, (PyObject *) Y);
|
|
1081
|
+
}
|
|
1082
|
+
else {
|
|
1083
|
+
BN_free(y);
|
|
1084
|
+
ECElement *newObj = createNewPoint(ZR, gobj);
|
|
1085
|
+
BN_copy(newObj->elemZ, x);
|
|
1086
|
+
BN_free(x);
|
|
1087
|
+
return (PyObject *) newObj;
|
|
1088
|
+
}
|
|
1089
|
+
}
|
|
1090
|
+
}
|
|
1091
|
+
}
|
|
1092
|
+
|
|
1093
|
+
EXIT_IF(TRUE, "invalid type.");
|
|
1094
|
+
}
|
|
1095
|
+
EXIT_IF(TRUE, "invalid argument.");
|
|
1096
|
+
}
|
|
1097
|
+
|
|
1098
|
+
static PyObject *ECE_getOrder(ECElement *self, PyObject *arg) {
|
|
1099
|
+
if(PyECGroup_Check(arg)) {
|
|
1100
|
+
ECGroup *gobj = (ECGroup*) arg;
|
|
1101
|
+
VERIFY_GROUP(gobj);
|
|
1102
|
+
|
|
1103
|
+
ECElement *order = createNewPoint(ZR, gobj);
|
|
1104
|
+
BN_copy(order->elemZ, gobj->order);
|
|
1105
|
+
// return the order of the group
|
|
1106
|
+
return (PyObject *) order;
|
|
1107
|
+
}
|
|
1108
|
+
EXIT_IF(TRUE, "invalid argument.");
|
|
1109
|
+
}
|
|
1110
|
+
|
|
1111
|
+
static PyObject *ECE_bitsize(ECElement *self, PyObject *arg) {
|
|
1112
|
+
if(PyECGroup_Check(arg)) {
|
|
1113
|
+
ECGroup *gobj = (ECGroup *) arg;
|
|
1114
|
+
VERIFY_GROUP(gobj);
|
|
1115
|
+
|
|
1116
|
+
size_t max_len = BN_num_bytes(gobj->order) - RESERVED_ENCODING_BYTES;
|
|
1117
|
+
debug("order len in bytes => '%zd'\n", max_len);
|
|
1118
|
+
|
|
1119
|
+
// maximum bitsize for messages encoded for the selected group
|
|
1120
|
+
return Py_BuildValue("i", max_len);
|
|
1121
|
+
}
|
|
1122
|
+
EXIT_IF(TRUE, "invalid argument.");
|
|
1123
|
+
}
|
|
1124
|
+
|
|
1125
|
+
|
|
1126
|
+
static PyObject *ECE_equals(PyObject *o1, PyObject *o2, int opid) {
|
|
1127
|
+
EXIT_IF(opid != Py_EQ && opid != Py_NE, "'==' and '!=' only comparisons supported.");
|
|
1128
|
+
|
|
1129
|
+
int foundLongLHS = FALSE, foundLongRHS = FALSE, result = FALSE;
|
|
1130
|
+
ECElement *lhs = NULL, *rhs = NULL;
|
|
1131
|
+
Check_Types2(o1, o2, lhs, rhs, foundLongLHS, foundLongRHS);
|
|
1132
|
+
|
|
1133
|
+
if(foundLongLHS) {
|
|
1134
|
+
if(rhs->type == ZR) {
|
|
1135
|
+
BIGNUM *lhs_val = BN_new();
|
|
1136
|
+
BN_set_word(lhs_val, PyLong_ToUnsignedLong(o1));
|
|
1137
|
+
if(BN_cmp(lhs_val, rhs->elemZ) == 0) {
|
|
1138
|
+
if(opid == Py_EQ) result = TRUE;
|
|
1139
|
+
}
|
|
1140
|
+
else if(opid == Py_NE) result = TRUE;
|
|
1141
|
+
BN_free(lhs_val);
|
|
1142
|
+
}
|
|
1143
|
+
else {
|
|
1144
|
+
EXIT_IF(TRUE, "comparison types not supported."); }
|
|
1145
|
+
}
|
|
1146
|
+
else if(foundLongRHS) {
|
|
1147
|
+
if(lhs->type == ZR) {
|
|
1148
|
+
BIGNUM *rhs_val = BN_new();
|
|
1149
|
+
BN_set_word(rhs_val, PyLong_ToUnsignedLong(o2));
|
|
1150
|
+
if(BN_cmp(lhs->elemZ, rhs_val) == 0) {
|
|
1151
|
+
if(opid == Py_EQ) result = TRUE;
|
|
1152
|
+
}
|
|
1153
|
+
else if(opid == Py_NE) result = TRUE;
|
|
1154
|
+
BN_free(rhs_val);
|
|
1155
|
+
}
|
|
1156
|
+
else {
|
|
1157
|
+
|
|
1158
|
+
EXIT_IF(TRUE, "comparison types not supported."); }
|
|
1159
|
+
}
|
|
1160
|
+
else {
|
|
1161
|
+
// Point_Init(lhs)
|
|
1162
|
+
// Point_Init(rhs)
|
|
1163
|
+
|
|
1164
|
+
if(ElementG(lhs, rhs)) {
|
|
1165
|
+
if(EC_POINT_cmp(lhs->group->ec_group, lhs->P, rhs->P, lhs->group->ctx) == 0) {
|
|
1166
|
+
if(opid == Py_EQ) result = TRUE;
|
|
1167
|
+
}
|
|
1168
|
+
else if(opid == Py_NE) result = TRUE;
|
|
1169
|
+
}
|
|
1170
|
+
else if(ElementZR(lhs, rhs)) {
|
|
1171
|
+
if(BN_cmp(lhs->elemZ, rhs->elemZ) == 0) {
|
|
1172
|
+
if(opid == Py_EQ) result = TRUE;
|
|
1173
|
+
}
|
|
1174
|
+
else if(opid == Py_NE) result = TRUE;
|
|
1175
|
+
}
|
|
1176
|
+
else {
|
|
1177
|
+
|
|
1178
|
+
EXIT_IF(TRUE, "cannot compare point to an integer.\n"); }
|
|
1179
|
+
}
|
|
1180
|
+
|
|
1181
|
+
/* return the result here */
|
|
1182
|
+
if(result) {
|
|
1183
|
+
Py_INCREF(Py_True);
|
|
1184
|
+
return Py_True;
|
|
1185
|
+
}
|
|
1186
|
+
|
|
1187
|
+
Py_INCREF(Py_False);
|
|
1188
|
+
return Py_False;
|
|
1189
|
+
}
|
|
1190
|
+
|
|
1191
|
+
static PyObject *ECE_getGen(ECElement *self, PyObject *arg) {
|
|
1192
|
+
if(PyECGroup_Check(arg)) {
|
|
1193
|
+
ECGroup *gobj = (ECGroup *) arg;
|
|
1194
|
+
VERIFY_GROUP(gobj);
|
|
1195
|
+
|
|
1196
|
+
ECElement *genObj = createNewPoint(G, gobj);
|
|
1197
|
+
const EC_POINT *gen = EC_GROUP_get0_generator(gobj->ec_group);
|
|
1198
|
+
EC_POINT_copy(genObj->P, gen);
|
|
1199
|
+
|
|
1200
|
+
return (PyObject *) genObj;
|
|
1201
|
+
}
|
|
1202
|
+
EXIT_IF(TRUE, "invalid argument.");
|
|
1203
|
+
}
|
|
1204
|
+
|
|
1205
|
+
/*
|
|
1206
|
+
* Takes an arbitrary string and returns a group element
|
|
1207
|
+
*/
|
|
1208
|
+
void set_element_from_hash(ECElement *self, uint8_t *input, int input_len)
|
|
1209
|
+
{
|
|
1210
|
+
if (self->type != G) {
|
|
1211
|
+
PyErr_SetString(PyECErrorObject, "element not of type G.");
|
|
1212
|
+
}
|
|
1213
|
+
|
|
1214
|
+
BIGNUM *x = BN_new(), *y = BN_new();
|
|
1215
|
+
int TryNextX = TRUE;
|
|
1216
|
+
BN_CTX *ctx = BN_CTX_new();
|
|
1217
|
+
ECGroup *gobj = self->group;
|
|
1218
|
+
// assume input string is a binary string, then set x to (x mod q)
|
|
1219
|
+
BN_bin2bn((const uint8_t *) input, input_len, x);
|
|
1220
|
+
BN_mod(x, x, gobj->order, ctx);
|
|
1221
|
+
do {
|
|
1222
|
+
// set x coordinate and then test whether it's on curve
|
|
1223
|
+
#ifdef DEBUG
|
|
1224
|
+
char *xstr = BN_bn2dec(x);
|
|
1225
|
+
debug("Generating another x => %s\n", xstr);
|
|
1226
|
+
OPENSSL_free(xstr);
|
|
1227
|
+
#endif
|
|
1228
|
+
EC_POINT_set_compressed_coordinates_GFp(gobj->ec_group, self->P, x, 1, ctx);
|
|
1229
|
+
EC_POINT_get_affine_coordinates_GFp(gobj->ec_group, self->P, x, y, ctx);
|
|
1230
|
+
|
|
1231
|
+
if(BN_is_zero(x) || BN_is_zero(y)) {
|
|
1232
|
+
BN_add(x, x, BN_value_one());
|
|
1233
|
+
continue;
|
|
1234
|
+
}
|
|
1235
|
+
|
|
1236
|
+
if(EC_POINT_is_on_curve(gobj->ec_group, self->P, ctx)) {
|
|
1237
|
+
TryNextX = FALSE;
|
|
1238
|
+
}
|
|
1239
|
+
else {
|
|
1240
|
+
BN_add(x, x, BN_value_one());
|
|
1241
|
+
}
|
|
1242
|
+
}while(TryNextX);
|
|
1243
|
+
|
|
1244
|
+
BN_free(x);
|
|
1245
|
+
BN_free(y);
|
|
1246
|
+
BN_CTX_free(ctx);
|
|
1247
|
+
}
|
|
1248
|
+
|
|
1249
|
+
static PyObject *ECE_hash(ECElement *self, PyObject *args) {
|
|
1250
|
+
|
|
1251
|
+
char *msg = NULL;
|
|
1252
|
+
Py_ssize_t msg_len;
|
|
1253
|
+
GroupType type;
|
|
1254
|
+
ECElement *hashObj = NULL;
|
|
1255
|
+
ECGroup *gobj = NULL;
|
|
1256
|
+
|
|
1257
|
+
if(PyArg_ParseTuple(args, "Os#i", &gobj, &msg, &msg_len, &type)) {
|
|
1258
|
+
VERIFY_GROUP(gobj);
|
|
1259
|
+
// compute bit size of group
|
|
1260
|
+
int hash_len = BN_num_bytes(gobj->order);
|
|
1261
|
+
debug("hash_len => %d\n", hash_len);
|
|
1262
|
+
uint8_t hash_buf[hash_len+1];
|
|
1263
|
+
if(type == G) {
|
|
1264
|
+
// hash input bytes
|
|
1265
|
+
hash_to_bytes((uint8_t *) msg, (int) msg_len, hash_buf, hash_len, HASH_FUNCTION_STR_TO_G_CRH);
|
|
1266
|
+
debug("Message => '%s'\n", msg);
|
|
1267
|
+
debug("Digest => ");
|
|
1268
|
+
printf_buffer_as_hex(hash_buf, hash_len);
|
|
1269
|
+
// generate an EC element from message digest
|
|
1270
|
+
hashObj = createNewPoint(G, gobj);
|
|
1271
|
+
set_element_from_hash(hashObj, (uint8_t *) hash_buf, hash_len);
|
|
1272
|
+
return (PyObject *) hashObj;
|
|
1273
|
+
}
|
|
1274
|
+
else if(type == ZR) {
|
|
1275
|
+
hash_to_bytes((uint8_t *) msg, (int) msg_len, hash_buf, hash_len, HASH_FUNCTION_STR_TO_ZR_CRH);
|
|
1276
|
+
debug("Message => '%s'\n", msg);
|
|
1277
|
+
debug("Digest => ");
|
|
1278
|
+
printf_buffer_as_hex(hash_buf, hash_len);
|
|
1279
|
+
|
|
1280
|
+
hashObj = createNewPoint(ZR, gobj);
|
|
1281
|
+
BN_bin2bn((const uint8_t *) hash_buf, hash_len, hashObj->elemZ);
|
|
1282
|
+
return (PyObject *) hashObj;
|
|
1283
|
+
}
|
|
1284
|
+
else {
|
|
1285
|
+
|
|
1286
|
+
EXIT_IF(TRUE, "invalid argument type");
|
|
1287
|
+
}
|
|
1288
|
+
}
|
|
1289
|
+
|
|
1290
|
+
|
|
1291
|
+
EXIT_IF(TRUE, "invalid arguments");
|
|
1292
|
+
}
|
|
1293
|
+
|
|
1294
|
+
/*
|
|
1295
|
+
* Encode a message as a group element
|
|
1296
|
+
*/
|
|
1297
|
+
static PyObject *ECE_encode(ECElement *self, PyObject *args) {
|
|
1298
|
+
PyObject *old_m;
|
|
1299
|
+
uint8_t *old_msg;
|
|
1300
|
+
int include_ctr = FALSE;
|
|
1301
|
+
uint32_t msg_len, ctr = 1, ERROR_SET = FALSE; // always have a ctr start from 1
|
|
1302
|
+
BIGNUM *x = NULL, *y = NULL;
|
|
1303
|
+
ECGroup *gobj = NULL;
|
|
1304
|
+
|
|
1305
|
+
if(PyArg_ParseTuple(args, "OO|i", &gobj, &old_m, &include_ctr)) {
|
|
1306
|
+
VERIFY_GROUP(gobj);
|
|
1307
|
+
|
|
1308
|
+
if(PyBytes_Check(old_m)) {
|
|
1309
|
+
old_msg = (uint8_t *) PyBytes_AS_STRING(old_m);
|
|
1310
|
+
msg_len = PyBytes_Size(old_m);
|
|
1311
|
+
debug("Encoding hex msg => ");
|
|
1312
|
+
// check if msg len is big enough to fit into length
|
|
1313
|
+
printf_buffer_as_hex((uint8_t *) old_msg, msg_len);
|
|
1314
|
+
debug("len => '%d'\n", msg_len);
|
|
1315
|
+
}
|
|
1316
|
+
else {
|
|
1317
|
+
/* return error */
|
|
1318
|
+
EXIT_IF(TRUE, "message not a bytes object");
|
|
1319
|
+
}
|
|
1320
|
+
|
|
1321
|
+
// make sure msg will fit into group (get order num bits / 8)
|
|
1322
|
+
int max_len = BN_num_bytes(gobj->order); // (BN_num_bits(gobj->order) / BYTE);
|
|
1323
|
+
debug("max msg len => '%d'\n", max_len);
|
|
1324
|
+
|
|
1325
|
+
debug("msg_len accepted => '%d'\n", msg_len);
|
|
1326
|
+
int len = msg_len;
|
|
1327
|
+
if (include_ctr == FALSE) {
|
|
1328
|
+
len += RESERVED_ENCODING_BYTES;
|
|
1329
|
+
}
|
|
1330
|
+
|
|
1331
|
+
// use default of 32-bits (4 bytes) to represent ctr
|
|
1332
|
+
// concatenate 'ctr' to buffer and set x coordinate and test for y coordiate on curve
|
|
1333
|
+
// if point not on curve, increment ctr by 1
|
|
1334
|
+
if(len == max_len) {
|
|
1335
|
+
// concatenate msg
|
|
1336
|
+
char *input = (char *) malloc(len + 1);
|
|
1337
|
+
if (input == NULL) {
|
|
1338
|
+
PyErr_SetString(PyExc_MemoryError, "Failed to allocate memory for input buffer");
|
|
1339
|
+
return NULL;
|
|
1340
|
+
}
|
|
1341
|
+
memset(input, 0, len);
|
|
1342
|
+
memcpy(input, old_msg, msg_len);
|
|
1343
|
+
int TryNextCTR = TRUE;
|
|
1344
|
+
ECElement *encObj = NULL;
|
|
1345
|
+
y=BN_new();
|
|
1346
|
+
x=BN_new();
|
|
1347
|
+
do {
|
|
1348
|
+
|
|
1349
|
+
if(encObj!=NULL)
|
|
1350
|
+
Py_DECREF(encObj);
|
|
1351
|
+
|
|
1352
|
+
if (include_ctr == FALSE) {
|
|
1353
|
+
/* == msg_len ctr
|
|
1354
|
+
* encoding [ message | \x01 \x00 \x00 \x00 ]
|
|
1355
|
+
*/
|
|
1356
|
+
*((uint32_t*)(input + msg_len)) = (uint32_t) ctr;
|
|
1357
|
+
}
|
|
1358
|
+
|
|
1359
|
+
debug("input hex msg => ");
|
|
1360
|
+
// check if msg len is big enough to fit into length
|
|
1361
|
+
printf_buffer_as_hex((uint8_t *) input, len);
|
|
1362
|
+
encObj = createNewPoint(G, gobj);
|
|
1363
|
+
BN_bin2bn((const uint8_t *) input, len, x);
|
|
1364
|
+
BN_free(y);
|
|
1365
|
+
y = BN_new();
|
|
1366
|
+
// Uncomment for debugging purposes
|
|
1367
|
+
//char *xstr = BN_bn2dec(x);
|
|
1368
|
+
//debug("gen x => %s\n", xstr);
|
|
1369
|
+
//OPENSSL_free(xstr);
|
|
1370
|
+
EC_POINT_set_compressed_coordinates_GFp(gobj->ec_group, encObj->P, x, 1, gobj->ctx);
|
|
1371
|
+
EC_POINT_get_affine_coordinates_GFp(gobj->ec_group, encObj->P, x, y, gobj->ctx);
|
|
1372
|
+
|
|
1373
|
+
if(BN_is_zero(x) || BN_is_zero(y)) {
|
|
1374
|
+
ctr++;
|
|
1375
|
+
continue;
|
|
1376
|
+
}
|
|
1377
|
+
|
|
1378
|
+
if(EC_POINT_is_on_curve(gobj->ec_group, encObj->P, gobj->ctx)) {
|
|
1379
|
+
debug("point is on curve!\n");
|
|
1380
|
+
debug("final hex msg => ");
|
|
1381
|
+
// check if msg len is big enough to fit into length
|
|
1382
|
+
printf_buffer_as_hex((uint8_t *) input, len);
|
|
1383
|
+
free(input);
|
|
1384
|
+
TryNextCTR = FALSE;
|
|
1385
|
+
}
|
|
1386
|
+
else {
|
|
1387
|
+
ctr++;
|
|
1388
|
+
}
|
|
1389
|
+
}while(TryNextCTR);
|
|
1390
|
+
|
|
1391
|
+
BN_free(x);
|
|
1392
|
+
BN_free(y);
|
|
1393
|
+
|
|
1394
|
+
return (PyObject *) encObj;
|
|
1395
|
+
}
|
|
1396
|
+
else {
|
|
1397
|
+
printf("expected message len: %lu, you provided: %d\n", (max_len - sizeof(uint32_t)), msg_len);
|
|
1398
|
+
EXIT_IF(TRUE, "message length does not match the selected group size.");
|
|
1399
|
+
}
|
|
1400
|
+
}
|
|
1401
|
+
|
|
1402
|
+
EXIT_IF(ERROR_SET, "Ran out of counters. So, could not be encode message at given length. make it smaller.");
|
|
1403
|
+
Py_INCREF(Py_False);
|
|
1404
|
+
|
|
1405
|
+
return Py_False;
|
|
1406
|
+
}
|
|
1407
|
+
|
|
1408
|
+
|
|
1409
|
+
/*
|
|
1410
|
+
* Decode a group element to a message (PyUnicode_String)
|
|
1411
|
+
*/
|
|
1412
|
+
static PyObject *ECE_decode(ECElement *self, PyObject *args) {
|
|
1413
|
+
ECElement *obj = NULL;
|
|
1414
|
+
ECGroup *gobj = NULL;
|
|
1415
|
+
int include_ctr = FALSE;
|
|
1416
|
+
|
|
1417
|
+
if(PyArg_ParseTuple(args, "OO|i", &gobj, &obj, &include_ctr)) {
|
|
1418
|
+
VERIFY_GROUP(gobj);
|
|
1419
|
+
|
|
1420
|
+
// make sure it is a point and not a scalar
|
|
1421
|
+
if(PyEC_Check(obj) && isPoint(obj)) {
|
|
1422
|
+
BIGNUM *x = BN_new(), *y = BN_new();
|
|
1423
|
+
// verifies that element is on the curve then gets coordinates
|
|
1424
|
+
EC_POINT_get_affine_coordinates_GFp(gobj->ec_group, obj->P, x, y, gobj->ctx);
|
|
1425
|
+
int max_byte_len = BN_num_bytes(gobj->order);
|
|
1426
|
+
int prepend_zeros = max_byte_len;
|
|
1427
|
+
// by default we will strip out the counter part (unless specified otherwise by user)
|
|
1428
|
+
if (include_ctr == FALSE) {
|
|
1429
|
+
max_byte_len -= RESERVED_ENCODING_BYTES;
|
|
1430
|
+
}
|
|
1431
|
+
debug("Size of order => '%d'\n", max_byte_len);
|
|
1432
|
+
int x_len = BN_num_bytes(x);
|
|
1433
|
+
prepend_zeros -= x_len;
|
|
1434
|
+
if (prepend_zeros > 0) {
|
|
1435
|
+
x_len += prepend_zeros;
|
|
1436
|
+
}
|
|
1437
|
+
uint8_t *xstr = (uint8_t*) malloc(x_len + 1);
|
|
1438
|
+
if (xstr == NULL) {
|
|
1439
|
+
PyErr_SetString(PyExc_MemoryError, "Failed to allocate memory for xstr buffer");
|
|
1440
|
+
BN_free(x);
|
|
1441
|
+
BN_free(y);
|
|
1442
|
+
return NULL;
|
|
1443
|
+
}
|
|
1444
|
+
memset(xstr, 0, x_len);
|
|
1445
|
+
debug("Size of xstr => '%d'\n", x_len);
|
|
1446
|
+
// BN_bn2bin does not include leading null bytes that might've been included in original message
|
|
1447
|
+
// so doing that here by counting length and then pre-pending zeroes
|
|
1448
|
+
BN_bn2bin(x, (uint8_t*)(xstr + prepend_zeros));
|
|
1449
|
+
debug("Decoded x => ");
|
|
1450
|
+
printf_buffer_as_hex((uint8_t *) (xstr), x_len);
|
|
1451
|
+
BN_free(x);
|
|
1452
|
+
BN_free(y);
|
|
1453
|
+
|
|
1454
|
+
int size_msg = max_byte_len;
|
|
1455
|
+
PyObject *decObj = PyBytes_FromStringAndSize((const char *)xstr, size_msg);
|
|
1456
|
+
OPENSSL_free(xstr);
|
|
1457
|
+
return decObj;
|
|
1458
|
+
}
|
|
1459
|
+
}
|
|
1460
|
+
|
|
1461
|
+
EXIT_IF(TRUE, "invalid argument");
|
|
1462
|
+
}
|
|
1463
|
+
|
|
1464
|
+
static PyObject *Serialize(ECElement *self, PyObject *args) {
|
|
1465
|
+
|
|
1466
|
+
ECElement *obj = NULL;
|
|
1467
|
+
if(!PyArg_ParseTuple(args, "O", &obj)) {
|
|
1468
|
+
ErrorMsg("invalid argument.");
|
|
1469
|
+
return NULL;
|
|
1470
|
+
}
|
|
1471
|
+
|
|
1472
|
+
if(obj != NULL && PyEC_Check(obj)) {
|
|
1473
|
+
// allows export a compressed string
|
|
1474
|
+
if(obj->point_init && obj->type == G) {
|
|
1475
|
+
uint8_t p_buf[MAX_BUF+1];
|
|
1476
|
+
memset(p_buf, 0, MAX_BUF);
|
|
1477
|
+
size_t len = EC_POINT_point2oct(obj->group->ec_group, obj->P, POINT_CONVERSION_COMPRESSED, p_buf, MAX_BUF, obj->group->ctx);
|
|
1478
|
+
EXIT_IF(len == 0, "could not serialize point.");
|
|
1479
|
+
|
|
1480
|
+
debug("Serialized point => ");
|
|
1481
|
+
printf_buffer_as_hex(p_buf, len);
|
|
1482
|
+
size_t length = 0;
|
|
1483
|
+
char *base64_buf = NewBase64Encode(p_buf, len, FALSE, &length);
|
|
1484
|
+
|
|
1485
|
+
PyObject *result = PyBytes_FromString((const char *) base64_buf);
|
|
1486
|
+
PyObject *obj2 = PyBytes_FromFormat("%d:", obj->type);
|
|
1487
|
+
PyBytes_ConcatAndDel(&obj2, result);
|
|
1488
|
+
free(base64_buf);
|
|
1489
|
+
return obj2;
|
|
1490
|
+
}
|
|
1491
|
+
else if(obj->point_init && obj->type == ZR) {
|
|
1492
|
+
size_t len = BN_num_bytes(obj->elemZ);
|
|
1493
|
+
uint8_t z_buf[len+1];
|
|
1494
|
+
memset(z_buf, 0, len);
|
|
1495
|
+
if((size_t)BN_bn2bin(obj->elemZ, z_buf) == len) {
|
|
1496
|
+
// we're okay
|
|
1497
|
+
// convert z_buf to base64 and the rest is history.
|
|
1498
|
+
size_t length = 0;
|
|
1499
|
+
char *base64_buf = NewBase64Encode(z_buf, len, FALSE, &length);
|
|
1500
|
+
|
|
1501
|
+
PyObject *result = PyBytes_FromString((const char *) base64_buf);
|
|
1502
|
+
PyObject *obj2 = PyBytes_FromFormat("%d:", obj->type);
|
|
1503
|
+
PyBytes_ConcatAndDel(&obj2, result);
|
|
1504
|
+
free(base64_buf);
|
|
1505
|
+
return obj2;
|
|
1506
|
+
}
|
|
1507
|
+
}
|
|
1508
|
+
}
|
|
1509
|
+
|
|
1510
|
+
|
|
1511
|
+
return NULL;
|
|
1512
|
+
}
|
|
1513
|
+
|
|
1514
|
+
static PyObject *Deserialize(ECElement *self, PyObject *args)
|
|
1515
|
+
{
|
|
1516
|
+
PyObject *obj = NULL;
|
|
1517
|
+
ECGroup *gobj = NULL;
|
|
1518
|
+
|
|
1519
|
+
if(PyArg_ParseTuple(args, "OO", &gobj, &obj)) {
|
|
1520
|
+
VERIFY_GROUP(gobj);
|
|
1521
|
+
if(PyBytes_Check(obj)) {
|
|
1522
|
+
unsigned char *serial_buf = (unsigned char *) PyBytes_AsString(obj);
|
|
1523
|
+
GroupType type = atoi((const char *) &(serial_buf[0]));
|
|
1524
|
+
uint8_t *base64_buf = (uint8_t *)(serial_buf + 2);
|
|
1525
|
+
|
|
1526
|
+
size_t deserialized_len = 0;
|
|
1527
|
+
uint8_t *buf = NewBase64Decode((const char *) base64_buf, strlen((char *) base64_buf), &deserialized_len);
|
|
1528
|
+
size_t len = deserialized_len;
|
|
1529
|
+
debug("Deserialize this => ");
|
|
1530
|
+
printf_buffer_as_hex(buf, len);
|
|
1531
|
+
if(type == G) {
|
|
1532
|
+
ECElement *newObj = createNewPoint(type, gobj); // ->group, gobj->ctx);
|
|
1533
|
+
EC_POINT_oct2point(gobj->ec_group, newObj->P, (const uint8_t *) buf, len, gobj->ctx);
|
|
1534
|
+
|
|
1535
|
+
if(EC_POINT_is_on_curve(gobj->ec_group, newObj->P, gobj->ctx)) {
|
|
1536
|
+
obj=(PyObject *) newObj;
|
|
1537
|
+
}
|
|
1538
|
+
}
|
|
1539
|
+
else if(type == ZR) {
|
|
1540
|
+
ECElement *newObj = createNewPoint(type, gobj);
|
|
1541
|
+
BN_bin2bn((const uint8_t *) buf, len, newObj->elemZ);
|
|
1542
|
+
obj = (PyObject *) newObj;
|
|
1543
|
+
}else{
|
|
1544
|
+
Py_INCREF(Py_False);
|
|
1545
|
+
obj = Py_False;
|
|
1546
|
+
}
|
|
1547
|
+
free(buf);
|
|
1548
|
+
return obj;
|
|
1549
|
+
}
|
|
1550
|
+
else {
|
|
1551
|
+
EXIT_IF(TRUE, "invalid object type");
|
|
1552
|
+
}
|
|
1553
|
+
}
|
|
1554
|
+
EXIT_IF(TRUE, "invalid argument");
|
|
1555
|
+
}
|
|
1556
|
+
|
|
1557
|
+
#ifdef BENCHMARK_ENABLED
|
|
1558
|
+
|
|
1559
|
+
#define BenchmarkIdentifier 2
|
|
1560
|
+
#define GET_RESULTS_FUNC GetResults
|
|
1561
|
+
#define GROUP_OBJECT ECGroup
|
|
1562
|
+
#define BENCH_ERROR PyECErrorObject
|
|
1563
|
+
|
|
1564
|
+
PyObject *PyCreateList(Operations *gBench, MeasureType type)
|
|
1565
|
+
{
|
|
1566
|
+
int countZR = -1, countG = -1;
|
|
1567
|
+
GetField(countZR, type, ZR, gBench);
|
|
1568
|
+
GetField(countG, type, G, gBench);
|
|
1569
|
+
|
|
1570
|
+
PyObject *objList = Py_BuildValue("[ii]", countZR, countG);
|
|
1571
|
+
return objList;
|
|
1572
|
+
}
|
|
1573
|
+
|
|
1574
|
+
#include "benchmark_util.c"
|
|
1575
|
+
|
|
1576
|
+
#endif
|
|
1577
|
+
|
|
1578
|
+
PyMemberDef ECElement_members[] = {
|
|
1579
|
+
{"type", T_INT, offsetof(ECElement, type), 0,
|
|
1580
|
+
"group type"},
|
|
1581
|
+
{"initialized", T_INT, offsetof(ECElement, point_init), 0,
|
|
1582
|
+
"determine initialization status"},
|
|
1583
|
+
{NULL} /* Sentinel */
|
|
1584
|
+
};
|
|
1585
|
+
|
|
1586
|
+
PyMethodDef ECElement_methods[] = {
|
|
1587
|
+
{"isInf", (PyCFunction)ECE_is_infinity, METH_NOARGS, "Checks whether a point is at infinity."},
|
|
1588
|
+
{NULL}
|
|
1589
|
+
};
|
|
1590
|
+
|
|
1591
|
+
#if PY_MAJOR_VERSION >= 3
|
|
1592
|
+
PyNumberMethods ec_number = {
|
|
1593
|
+
(binaryfunc) ECE_add, /* nb_add */
|
|
1594
|
+
(binaryfunc) ECE_sub, /* nb_subtract */
|
|
1595
|
+
(binaryfunc) ECE_mul, /* nb_multiply */
|
|
1596
|
+
(binaryfunc) ECE_rem, /* nb_remainder */
|
|
1597
|
+
0, /* nb_divmod */
|
|
1598
|
+
(ternaryfunc) ECE_pow, /* nb_power */
|
|
1599
|
+
(unaryfunc) ECE_neg, /* nb_negative */
|
|
1600
|
+
0, /* nb_positive */
|
|
1601
|
+
0, /* nb_absolute */
|
|
1602
|
+
0, /* nb_bool */
|
|
1603
|
+
(unaryfunc)ECE_invert, /* nb_invert */
|
|
1604
|
+
0, /* nb_lshift */
|
|
1605
|
+
0, /* nb_rshift */
|
|
1606
|
+
0, /* nb_and */
|
|
1607
|
+
0, /* nb_xor */
|
|
1608
|
+
0, /* nb_or */
|
|
1609
|
+
(unaryfunc)ECE_long, /* nb_int */
|
|
1610
|
+
0, /* nb_reserved */
|
|
1611
|
+
0, /* nb_float */
|
|
1612
|
+
(binaryfunc) ECE_add, /* nb_inplace_add */
|
|
1613
|
+
(binaryfunc) ECE_sub, /* nb_inplace_subtract */
|
|
1614
|
+
(binaryfunc) ECE_mul, /* nb_inplace_multiply */
|
|
1615
|
+
(binaryfunc) ECE_rem, /* nb_inplace_remainder */
|
|
1616
|
+
(ternaryfunc) ECE_pow, /* nb_inplace_power */
|
|
1617
|
+
0, /* nb_inplace_lshift */
|
|
1618
|
+
0, /* nb_inplace_rshift */
|
|
1619
|
+
0, /* nb_inplace_and */
|
|
1620
|
+
0, /* nb_inplace_xor */
|
|
1621
|
+
0, /* nb_inplace_or */
|
|
1622
|
+
0, /* nb_floor_divide */
|
|
1623
|
+
ECE_div, /* nb_true_divide */
|
|
1624
|
+
0, /* nb_inplace_floor_divide */
|
|
1625
|
+
ECE_div, /* nb_inplace_true_divide */
|
|
1626
|
+
0, /* nb_index */
|
|
1627
|
+
};
|
|
1628
|
+
|
|
1629
|
+
PyTypeObject ECType = {
|
|
1630
|
+
PyVarObject_HEAD_INIT(NULL, 0)
|
|
1631
|
+
"elliptic_curve.Element", /*tp_name*/
|
|
1632
|
+
sizeof(ECElement), /*tp_basicsize*/
|
|
1633
|
+
0, /*tp_itemsize*/
|
|
1634
|
+
(destructor)ECElement_dealloc, /*tp_dealloc*/
|
|
1635
|
+
0, /*tp_print*/
|
|
1636
|
+
0, /*tp_getattr*/
|
|
1637
|
+
0, /*tp_setattr*/
|
|
1638
|
+
0, /*tp_reserved*/
|
|
1639
|
+
(reprfunc)ECElement_print, /*tp_repr*/
|
|
1640
|
+
&ec_number, /*tp_as_number*/
|
|
1641
|
+
0, /*tp_as_sequence*/
|
|
1642
|
+
0, /*tp_as_mapping*/
|
|
1643
|
+
0, /*tp_hash */
|
|
1644
|
+
0, /*tp_call*/
|
|
1645
|
+
(reprfunc)ECElement_print, /*tp_str*/
|
|
1646
|
+
0, /*tp_getattro*/
|
|
1647
|
+
0, /*tp_setattro*/
|
|
1648
|
+
0, /*tp_as_buffer*/
|
|
1649
|
+
Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /*tp_flags*/
|
|
1650
|
+
"Elliptic Curve objects", /* tp_doc */
|
|
1651
|
+
0, /* tp_traverse */
|
|
1652
|
+
0, /* tp_clear */
|
|
1653
|
+
ECE_equals, /* tp_richcompare */
|
|
1654
|
+
0, /* tp_weaklistoffset */
|
|
1655
|
+
0, /* tp_iter */
|
|
1656
|
+
0, /* tp_iternext */
|
|
1657
|
+
ECElement_methods, /* tp_methods */
|
|
1658
|
+
ECElement_members, /* tp_members */
|
|
1659
|
+
0, /* tp_getset */
|
|
1660
|
+
0, /* tp_base */
|
|
1661
|
+
0, /* tp_dict */
|
|
1662
|
+
0, /* tp_descr_get */
|
|
1663
|
+
0, /* tp_descr_set */
|
|
1664
|
+
0, /* tp_dictoffset */
|
|
1665
|
+
(initproc)ECElement_init, /* tp_init */
|
|
1666
|
+
0, /* tp_alloc */
|
|
1667
|
+
ECElement_new, /* tp_new */
|
|
1668
|
+
};
|
|
1669
|
+
#else
|
|
1670
|
+
/* python 2.x series */
|
|
1671
|
+
PyNumberMethods ec_number = {
|
|
1672
|
+
ECE_add, /* nb_add */
|
|
1673
|
+
ECE_sub, /* nb_subtract */
|
|
1674
|
+
ECE_mul, /* nb_multiply */
|
|
1675
|
+
ECE_div, /* nb_divide */
|
|
1676
|
+
ECE_rem, /* nb_remainder */
|
|
1677
|
+
0, /* nb_divmod */
|
|
1678
|
+
ECE_pow, /* nb_power */
|
|
1679
|
+
ECE_neg, /* nb_negative */
|
|
1680
|
+
0, /* nb_positive */
|
|
1681
|
+
0, /* nb_absolute */
|
|
1682
|
+
0, /* nb_nonzero */
|
|
1683
|
+
(unaryfunc)ECE_invert, /* nb_invert */
|
|
1684
|
+
0, /* nb_lshift */
|
|
1685
|
+
0, /* nb_rshift */
|
|
1686
|
+
0, /* nb_and */
|
|
1687
|
+
0, /* nb_xor */
|
|
1688
|
+
0, /* nb_or */
|
|
1689
|
+
0, /* nb_coerce */
|
|
1690
|
+
0, /* nb_int */
|
|
1691
|
+
(unaryfunc)ECE_long, /* nb_long */
|
|
1692
|
+
0, /* nb_float */
|
|
1693
|
+
0, /* nb_oct */
|
|
1694
|
+
0, /* nb_hex */
|
|
1695
|
+
ECE_add, /* nb_inplace_add */
|
|
1696
|
+
ECE_sub, /* nb_inplace_subtract */
|
|
1697
|
+
ECE_mul, /* nb_inplace_multiply */
|
|
1698
|
+
ECE_div, /* nb_inplace_divide */
|
|
1699
|
+
0, /* nb_inplace_remainder */
|
|
1700
|
+
0, /* nb_inplace_power */
|
|
1701
|
+
0, /* nb_inplace_lshift */
|
|
1702
|
+
0, /* nb_inplace_rshift */
|
|
1703
|
+
0, /* nb_inplace_and */
|
|
1704
|
+
0, /* nb_inplace_xor */
|
|
1705
|
+
0, /* nb_inplace_or */
|
|
1706
|
+
0, /* nb_floor_divide */
|
|
1707
|
+
0, /* nb_true_divide */
|
|
1708
|
+
0, /* nb_inplace_floor_divide */
|
|
1709
|
+
0, /* nb_inplace_true_divide */
|
|
1710
|
+
0, /* nb_index */
|
|
1711
|
+
};
|
|
1712
|
+
|
|
1713
|
+
PyTypeObject ECType = {
|
|
1714
|
+
PyObject_HEAD_INIT(NULL)
|
|
1715
|
+
0, /*ob_size*/
|
|
1716
|
+
"elliptic_curve.Element", /*tp_name*/
|
|
1717
|
+
sizeof(ECElement), /*tp_basicsize*/
|
|
1718
|
+
0, /*tp_itemsize*/
|
|
1719
|
+
(destructor)ECElement_dealloc, /*tp_dealloc*/
|
|
1720
|
+
0, /*tp_print*/
|
|
1721
|
+
0, /*tp_getattr*/
|
|
1722
|
+
0, /*tp_setattr*/
|
|
1723
|
+
0, /*tp_compare*/
|
|
1724
|
+
(reprfunc)ECElement_print, /*tp_repr*/
|
|
1725
|
+
&ec_number, /*tp_as_number*/
|
|
1726
|
+
0, /*tp_as_sequence*/
|
|
1727
|
+
0, /*tp_as_mapping*/
|
|
1728
|
+
0, /*tp_hash */
|
|
1729
|
+
0, /*tp_call*/
|
|
1730
|
+
(reprfunc)ECElement_print, /*tp_str*/
|
|
1731
|
+
0, /*tp_getattro*/
|
|
1732
|
+
0, /*tp_setattro*/
|
|
1733
|
+
0, /*tp_as_buffer*/
|
|
1734
|
+
Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_CHECKTYPES, /*tp_flags*/
|
|
1735
|
+
"Elliptic Curve objects", /* tp_doc */
|
|
1736
|
+
0, /* tp_traverse */
|
|
1737
|
+
0, /* tp_clear */
|
|
1738
|
+
ECE_equals, /* tp_richcompare */
|
|
1739
|
+
0, /* tp_weaklistoffset */
|
|
1740
|
+
0, /* tp_iter */
|
|
1741
|
+
0, /* tp_iternext */
|
|
1742
|
+
ECElement_methods, /* tp_methods */
|
|
1743
|
+
ECElement_members, /* tp_members */
|
|
1744
|
+
0, /* tp_getset */
|
|
1745
|
+
0, /* tp_base */
|
|
1746
|
+
0, /* tp_dict */
|
|
1747
|
+
0, /* tp_descr_get */
|
|
1748
|
+
0, /* tp_descr_set */
|
|
1749
|
+
0, /* tp_dictoffset */
|
|
1750
|
+
(initproc) ECElement_init, /* tp_init */
|
|
1751
|
+
0, /* tp_alloc */
|
|
1752
|
+
ECElement_new, /* tp_new */
|
|
1753
|
+
};
|
|
1754
|
+
|
|
1755
|
+
#endif
|
|
1756
|
+
|
|
1757
|
+
#if PY_MAJOR_VERSION >= 3
|
|
1758
|
+
|
|
1759
|
+
PyTypeObject ECGroupType = {
|
|
1760
|
+
PyVarObject_HEAD_INIT(NULL, 0)
|
|
1761
|
+
"elliptic_curve.ECGroup", /*tp_name*/
|
|
1762
|
+
sizeof(ECGroup), /*tp_basicsize*/
|
|
1763
|
+
0, /*tp_itemsize*/
|
|
1764
|
+
(destructor)ECGroup_dealloc, /*tp_dealloc*/
|
|
1765
|
+
0, /*tp_print*/
|
|
1766
|
+
0, /*tp_getattr*/
|
|
1767
|
+
0, /*tp_setattr*/
|
|
1768
|
+
0, /*tp_reserved*/
|
|
1769
|
+
(reprfunc)ECGroup_print, /*tp_str*/
|
|
1770
|
+
0, /*tp_as_number*/
|
|
1771
|
+
0, /*tp_as_sequence*/
|
|
1772
|
+
0, /*tp_as_mapping*/
|
|
1773
|
+
0, /*tp_hash */
|
|
1774
|
+
0, /*tp_call*/
|
|
1775
|
+
0, /*tp_str*/
|
|
1776
|
+
0, /*tp_getattro*/
|
|
1777
|
+
0, /*tp_setattro*/
|
|
1778
|
+
0, /*tp_as_buffer*/
|
|
1779
|
+
Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /*tp_flags*/
|
|
1780
|
+
"ECGroup parameters", /* tp_doc */
|
|
1781
|
+
0, /* tp_traverse */
|
|
1782
|
+
0, /* tp_clear */
|
|
1783
|
+
0, /* tp_richcompare */
|
|
1784
|
+
0, /* tp_weaklistoffset */
|
|
1785
|
+
0, /* tp_iter */
|
|
1786
|
+
0, /* tp_iternext */
|
|
1787
|
+
0, /* tp_methods */
|
|
1788
|
+
0, /* tp_members */
|
|
1789
|
+
0, /* tp_getset */
|
|
1790
|
+
0, /* tp_base */
|
|
1791
|
+
0, /* tp_dict */
|
|
1792
|
+
0, /* tp_descr_get */
|
|
1793
|
+
0, /* tp_descr_set */
|
|
1794
|
+
0, /* tp_dictoffset */
|
|
1795
|
+
(initproc)ECGroup_init, /* tp_init */
|
|
1796
|
+
0, /* tp_alloc */
|
|
1797
|
+
ECGroup_new, /* tp_new */
|
|
1798
|
+
};
|
|
1799
|
+
#else
|
|
1800
|
+
/* python 2.x series */
|
|
1801
|
+
PyTypeObject ECGroupType = {
|
|
1802
|
+
PyObject_HEAD_INIT(NULL)
|
|
1803
|
+
0, /*ob_size*/
|
|
1804
|
+
"elliptic_curve.ECGroup", /*tp_name*/
|
|
1805
|
+
sizeof(ECGroup), /*tp_basicsize*/
|
|
1806
|
+
0, /*tp_itemsize*/
|
|
1807
|
+
(destructor)ECGroup_dealloc, /*tp_dealloc*/
|
|
1808
|
+
0, /*tp_print*/
|
|
1809
|
+
0, /*tp_getattr*/
|
|
1810
|
+
0, /*tp_setattr*/
|
|
1811
|
+
0, /*tp_compare*/
|
|
1812
|
+
0, /*tp_repr*/
|
|
1813
|
+
0, /*tp_as_number*/
|
|
1814
|
+
0, /*tp_as_sequence*/
|
|
1815
|
+
0, /*tp_as_mapping*/
|
|
1816
|
+
0, /*tp_hash */
|
|
1817
|
+
0, /*tp_call*/
|
|
1818
|
+
(reprfunc)ECGroup_print, /*tp_str*/
|
|
1819
|
+
0, /*tp_getattro*/
|
|
1820
|
+
0, /*tp_setattro*/
|
|
1821
|
+
0, /*tp_as_buffer*/
|
|
1822
|
+
Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /*tp_flags*/
|
|
1823
|
+
"ECGroup parameters", /* tp_doc */
|
|
1824
|
+
0, /* tp_traverse */
|
|
1825
|
+
0, /* tp_clear */
|
|
1826
|
+
0, /* tp_richcompare */
|
|
1827
|
+
0, /* tp_weaklistoffset */
|
|
1828
|
+
0, /* tp_iter */
|
|
1829
|
+
0, /* tp_iternext */
|
|
1830
|
+
0, /* tp_methods */
|
|
1831
|
+
0, /* tp_members */
|
|
1832
|
+
0, /* tp_getset */
|
|
1833
|
+
0, /* tp_base */
|
|
1834
|
+
0, /* tp_dict */
|
|
1835
|
+
0, /* tp_descr_get */
|
|
1836
|
+
0, /* tp_descr_set */
|
|
1837
|
+
0, /* tp_dictoffset */
|
|
1838
|
+
(initproc) ECGroup_init, /* tp_init */
|
|
1839
|
+
0, /* tp_alloc */
|
|
1840
|
+
ECGroup_new, /* tp_new */
|
|
1841
|
+
};
|
|
1842
|
+
|
|
1843
|
+
#endif
|
|
1844
|
+
|
|
1845
|
+
|
|
1846
|
+
struct module_state {
|
|
1847
|
+
PyObject *error;
|
|
1848
|
+
//#ifdef BENCHMARK_ENABLED
|
|
1849
|
+
// Benchmark *dBench;
|
|
1850
|
+
//#endif
|
|
1851
|
+
};
|
|
1852
|
+
|
|
1853
|
+
#if PY_MAJOR_VERSION >= 3
|
|
1854
|
+
#define GETSTATE(m) ((struct module_state *) PyModule_GetState(m))
|
|
1855
|
+
#else
|
|
1856
|
+
#define GETSTATE(m) (&_state)
|
|
1857
|
+
static struct module_state _state;
|
|
1858
|
+
#endif
|
|
1859
|
+
|
|
1860
|
+
static PyMethodDef ec_methods[] = {
|
|
1861
|
+
{"init", (PyCFunction)ECE_init, METH_VARARGS, "Create an element in a specific group G or ZR."},
|
|
1862
|
+
{"random", (PyCFunction)ECE_random, METH_VARARGS, "Return a random element in a specific group G or ZR."},
|
|
1863
|
+
{"order", (PyCFunction)ECE_getOrder, METH_O, "Return the order of a group."},
|
|
1864
|
+
{"getGenerator", (PyCFunction)ECE_getGen, METH_O, "Get the generator of the group."},
|
|
1865
|
+
{"bitsize", (PyCFunction)ECE_bitsize, METH_O, "Returns number of bytes to represent a message."},
|
|
1866
|
+
{"serialize", (PyCFunction)Serialize, METH_VARARGS, "Serialize an element to a string"},
|
|
1867
|
+
{"deserialize", (PyCFunction)Deserialize, METH_VARARGS, "Deserialize an element to G or ZR"},
|
|
1868
|
+
{"hashEC", (PyCFunction)ECE_hash, METH_VARARGS, "Perform a hash of a string to a group element of G."},
|
|
1869
|
+
{"encode", (PyCFunction)ECE_encode, METH_VARARGS, "Encode string as a group element of G"},
|
|
1870
|
+
{"decode", (PyCFunction)ECE_decode, METH_VARARGS, "Decode group element to a string."},
|
|
1871
|
+
{"getXY", (PyCFunction)ECE_convertToZR, METH_VARARGS, "Returns the x and/or y coordinates of point on an elliptic curve."},
|
|
1872
|
+
#ifdef BENCHMARK_ENABLED
|
|
1873
|
+
{"InitBenchmark", (PyCFunction)InitBenchmark, METH_VARARGS, "Initialize a benchmark object"},
|
|
1874
|
+
{"StartBenchmark", (PyCFunction)StartBenchmark, METH_VARARGS, "Start a new benchmark with some options"},
|
|
1875
|
+
{"EndBenchmark", (PyCFunction)EndBenchmark, METH_VARARGS, "End a given benchmark"},
|
|
1876
|
+
{"GetBenchmark", (PyCFunction)GetBenchmark, METH_VARARGS, "Returns contents of a benchmark object"},
|
|
1877
|
+
{"GetGeneralBenchmarks", (PyCFunction)GetAllBenchmarks, METH_VARARGS, "Retrieve general benchmark info as a dictionary"},
|
|
1878
|
+
{"GetGranularBenchmarks", (PyCFunction) GranularBenchmark, METH_VARARGS, "Retrieve granular benchmarks as a dictionary"},
|
|
1879
|
+
#endif
|
|
1880
|
+
{NULL, NULL}
|
|
1881
|
+
};
|
|
1882
|
+
|
|
1883
|
+
|
|
1884
|
+
#if PY_MAJOR_VERSION >= 3
|
|
1885
|
+
static int ec_traverse(PyObject *m, visitproc visit, void *arg) {
|
|
1886
|
+
Py_VISIT(GETSTATE(m)->error);
|
|
1887
|
+
return 0;
|
|
1888
|
+
}
|
|
1889
|
+
|
|
1890
|
+
static int ec_clear(PyObject *m) {
|
|
1891
|
+
Py_CLEAR(GETSTATE(m)->error);
|
|
1892
|
+
Py_XDECREF(PyECErrorObject);
|
|
1893
|
+
return 0;
|
|
1894
|
+
}
|
|
1895
|
+
|
|
1896
|
+
static int ec_free(PyObject *m) {
|
|
1897
|
+
// Defensive cleanup for OpenSSL to prevent hangs during Python 3.12+ shutdown
|
|
1898
|
+
// Only cleanup if not in abnormal finalization state
|
|
1899
|
+
if(m != NULL && !CHARM_PY_IS_FINALIZING()) {
|
|
1900
|
+
// Note: OpenSSL 1.1.0+ handles cleanup automatically
|
|
1901
|
+
// This is a no-op for compatibility but prevents potential hangs
|
|
1902
|
+
}
|
|
1903
|
+
return 0;
|
|
1904
|
+
}
|
|
1905
|
+
|
|
1906
|
+
static struct PyModuleDef moduledef = {
|
|
1907
|
+
PyModuleDef_HEAD_INIT,
|
|
1908
|
+
"elliptic_curve",
|
|
1909
|
+
NULL,
|
|
1910
|
+
sizeof(struct module_state),
|
|
1911
|
+
ec_methods,
|
|
1912
|
+
NULL,
|
|
1913
|
+
ec_traverse,
|
|
1914
|
+
ec_clear,
|
|
1915
|
+
(freefunc) ec_free
|
|
1916
|
+
};
|
|
1917
|
+
|
|
1918
|
+
#define CLEAN_EXIT goto LEAVE;
|
|
1919
|
+
#define INITERROR return NULL
|
|
1920
|
+
PyMODINIT_FUNC
|
|
1921
|
+
PyInit_elliptic_curve(void) {
|
|
1922
|
+
#else
|
|
1923
|
+
#define CLEAN_EXIT goto LEAVE;
|
|
1924
|
+
#define INITERROR return
|
|
1925
|
+
void initelliptic_curve(void) {
|
|
1926
|
+
#endif
|
|
1927
|
+
PyObject *m;
|
|
1928
|
+
if(PyType_Ready(&ECGroupType) < 0)
|
|
1929
|
+
CLEAN_EXIT;
|
|
1930
|
+
if(PyType_Ready(&ECType) < 0)
|
|
1931
|
+
CLEAN_EXIT;
|
|
1932
|
+
#ifdef BENCHMARK_ENABLED
|
|
1933
|
+
if(import_benchmark() < 0)
|
|
1934
|
+
CLEAN_EXIT;
|
|
1935
|
+
if(PyType_Ready(&BenchmarkType) < 0)
|
|
1936
|
+
CLEAN_EXIT;
|
|
1937
|
+
if(PyType_Ready(&OperationsType) < 0)
|
|
1938
|
+
CLEAN_EXIT;
|
|
1939
|
+
#endif
|
|
1940
|
+
|
|
1941
|
+
#if PY_MAJOR_VERSION >= 3
|
|
1942
|
+
m = PyModule_Create(&moduledef);
|
|
1943
|
+
#else
|
|
1944
|
+
m = Py_InitModule("elliptic_curve", ec_methods);
|
|
1945
|
+
#endif
|
|
1946
|
+
|
|
1947
|
+
struct module_state *st = GETSTATE(m);
|
|
1948
|
+
st->error = PyErr_NewException("elliptic_curve.Error", NULL, NULL);
|
|
1949
|
+
if (st->error == NULL)
|
|
1950
|
+
CLEAN_EXIT;
|
|
1951
|
+
PyECErrorObject = st->error;
|
|
1952
|
+
Py_INCREF(PyECErrorObject);
|
|
1953
|
+
|
|
1954
|
+
Py_INCREF(&ECType);
|
|
1955
|
+
if(PyModule_AddObject(m, "ec_element", (PyObject *)&ECType) != 0)
|
|
1956
|
+
CLEAN_EXIT;
|
|
1957
|
+
Py_INCREF(&ECGroupType);
|
|
1958
|
+
if(PyModule_AddObject(m, "elliptic_curve", (PyObject *)&ECGroupType) != 0)
|
|
1959
|
+
CLEAN_EXIT;
|
|
1960
|
+
|
|
1961
|
+
PyModule_AddIntConstant(m, "G", G);
|
|
1962
|
+
PyModule_AddIntConstant(m, "ZR", ZR);
|
|
1963
|
+
#ifdef BENCHMARK_ENABLED
|
|
1964
|
+
ADD_BENCHMARK_OPTIONS(m);
|
|
1965
|
+
PyModule_AddStringConstant(m, "Granular", _GRAN_OPT);
|
|
1966
|
+
#endif
|
|
1967
|
+
// initialize PRNG
|
|
1968
|
+
// replace with read from some source of randomness
|
|
1969
|
+
#ifndef MS_WINDOWS
|
|
1970
|
+
debug("Linux: seeding openssl prng.\n");
|
|
1971
|
+
char *rand_file = "/dev/urandom";
|
|
1972
|
+
RAND_load_file(rand_file, RAND_MAX_BYTES);
|
|
1973
|
+
#else
|
|
1974
|
+
debug("Windows: seeding openssl prng.\n");
|
|
1975
|
+
RAND_poll();
|
|
1976
|
+
#endif
|
|
1977
|
+
|
|
1978
|
+
LEAVE:
|
|
1979
|
+
if (PyErr_Occurred()) {
|
|
1980
|
+
PyErr_Clear();
|
|
1981
|
+
Py_XDECREF(m);
|
|
1982
|
+
INITERROR;
|
|
1983
|
+
}
|
|
1984
|
+
|
|
1985
|
+
return m;
|
|
1986
|
+
}
|