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,2539 @@
|
|
|
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 integermodule.c
|
|
23
|
+
*
|
|
24
|
+
* @brief charm interface over GMP multi-precision integers
|
|
25
|
+
*
|
|
26
|
+
* @author jakinye3@jhu.edu
|
|
27
|
+
*
|
|
28
|
+
************************************************************************/
|
|
29
|
+
|
|
30
|
+
#include "integermodule.h"
|
|
31
|
+
|
|
32
|
+
/*
|
|
33
|
+
* Python 3.12+ changed the internal structure of PyLongObject:
|
|
34
|
+
* - Old (Python 3.11-): ob_size stores digit count (via Py_SIZE()), ob_digit is the digit array
|
|
35
|
+
* - New (Python 3.12+): long_value.lv_tag stores digit count, sign, and flags; long_value.ob_digit is the digit array
|
|
36
|
+
*
|
|
37
|
+
* In Python 3.12+:
|
|
38
|
+
* - lv_tag bits 0-1: Sign (0=positive, 1=zero, 2=negative)
|
|
39
|
+
* - lv_tag bit 2: Reserved for immortality
|
|
40
|
+
* - lv_tag bits 3+: Unsigned digit count
|
|
41
|
+
*
|
|
42
|
+
* We need to use different macros to access the digit array and get the digit count.
|
|
43
|
+
*/
|
|
44
|
+
|
|
45
|
+
#if PY_MINOR_VERSION >= 12
|
|
46
|
+
#define PythonLongVal(l) l->long_value.ob_digit
|
|
47
|
+
#define _PYLONG_NON_SIZE_BITS 3
|
|
48
|
+
#define _PYLONG_SIGN_MASK 3
|
|
49
|
+
#define _PYLONG_SIGN_NEGATIVE 2
|
|
50
|
+
#define _PYLONG_SIGN_ZERO 1
|
|
51
|
+
/* Get the digit count from lv_tag (bits 3+) */
|
|
52
|
+
#define PythonLongDigitCount(l) ((Py_ssize_t)(((PyLongObject *)(l))->long_value.lv_tag >> _PYLONG_NON_SIZE_BITS))
|
|
53
|
+
/* Check if negative (sign bits == 2) */
|
|
54
|
+
#define PythonLongIsNegative(l) ((((PyLongObject *)(l))->long_value.lv_tag & _PYLONG_SIGN_MASK) == _PYLONG_SIGN_NEGATIVE)
|
|
55
|
+
/* Set the digit count and sign in lv_tag */
|
|
56
|
+
#define PythonLongSetTag(l, sign, size) (((PyLongObject *)(l))->long_value.lv_tag = ((1 - (sign)) | ((size_t)(size) << _PYLONG_NON_SIZE_BITS)))
|
|
57
|
+
#else
|
|
58
|
+
#define PythonLongVal(l) l->ob_digit
|
|
59
|
+
/* In Python 3.11-, Py_SIZE() returns signed digit count (negative for negative numbers) */
|
|
60
|
+
#define PythonLongDigitCount(l) (Py_SIZE(l) < 0 ? -Py_SIZE(l) : Py_SIZE(l))
|
|
61
|
+
#define PythonLongIsNegative(l) (Py_SIZE(l) < 0)
|
|
62
|
+
/* Set the size (signed) */
|
|
63
|
+
#define PythonLongSetTag(l, sign, size) PYTHON_SET_SIZE(l, (sign) < 0 ? -(size) : (size))
|
|
64
|
+
#endif
|
|
65
|
+
|
|
66
|
+
#if PY_MINOR_VERSION <= 10
|
|
67
|
+
#define PYTHON_SET_SIZE(l, i) Py_SIZE(l) = i
|
|
68
|
+
#else
|
|
69
|
+
#define PYTHON_SET_SIZE(l, i) Py_SET_SIZE(l, i);
|
|
70
|
+
#endif
|
|
71
|
+
|
|
72
|
+
/*
|
|
73
|
+
* Python 3.13+ made Py_IsFinalizing() public and removed _Py_IsFinalizing().
|
|
74
|
+
* For older versions, we need to use the private _Py_IsFinalizing().
|
|
75
|
+
*/
|
|
76
|
+
#if PY_MINOR_VERSION >= 13
|
|
77
|
+
#define CHARM_PY_IS_FINALIZING() Py_IsFinalizing()
|
|
78
|
+
#else
|
|
79
|
+
#define CHARM_PY_IS_FINALIZING() _Py_IsFinalizing()
|
|
80
|
+
#endif
|
|
81
|
+
|
|
82
|
+
struct module_state {
|
|
83
|
+
PyObject *error;
|
|
84
|
+
#ifdef BENCHMARK_ENABLED
|
|
85
|
+
Benchmark *dBench;
|
|
86
|
+
#endif
|
|
87
|
+
};
|
|
88
|
+
|
|
89
|
+
#define GETSTATE(m) ((struct module_state *) PyModule_GetState(m))
|
|
90
|
+
|
|
91
|
+
#ifdef BENCHMARK_ENABLED
|
|
92
|
+
static Benchmark *tmpBench;
|
|
93
|
+
#endif
|
|
94
|
+
|
|
95
|
+
#define SET_BENCH(mod_obj, obj) \
|
|
96
|
+
struct module_state *st = GETSTATE(mod_obj); \
|
|
97
|
+
obj->dBench = (Benchmark *) st->dBench; \
|
|
98
|
+
Py_INCREF(obj->dBench);
|
|
99
|
+
//printf("%s: Refcnt dBench = '%i'\n", __FUNCTION__, (int) Py_REFCNT(obj->dBench));
|
|
100
|
+
|
|
101
|
+
#define COPY_BENCH(obj_dst, obj_src) \
|
|
102
|
+
if(obj_src->dBench != NULL && obj_dst->dBench == NULL) { \
|
|
103
|
+
obj_dst->dBench = obj_src->dBench; \
|
|
104
|
+
Py_INCREF(obj_dst->dBench); }
|
|
105
|
+
|
|
106
|
+
#define CAST_TO_LONG(obj, lng) \
|
|
107
|
+
if(PyLong_Check(obj)) { \
|
|
108
|
+
lng = PyLong_AsLong(obj); } \
|
|
109
|
+
else { \
|
|
110
|
+
Py_INCREF(Py_NotImplemented); \
|
|
111
|
+
return Py_NotImplemented; } \
|
|
112
|
+
|
|
113
|
+
|
|
114
|
+
static inline size_t size(mpz_t n) {
|
|
115
|
+
return mpz_sizeinbase(n, 2);
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
void longObjToMPZ(mpz_t m, PyObject * o) {
|
|
119
|
+
PyLongObject *p = (PyLongObject *) PyNumber_Long(o);
|
|
120
|
+
Py_ssize_t size, i;
|
|
121
|
+
int isNeg = FALSE;
|
|
122
|
+
mpz_t temp, temp2;
|
|
123
|
+
mpz_init(temp);
|
|
124
|
+
mpz_init(temp2);
|
|
125
|
+
|
|
126
|
+
/* Use the new macros that work correctly on both Python 3.11- and 3.12+ */
|
|
127
|
+
size = PythonLongDigitCount(p);
|
|
128
|
+
isNeg = PythonLongIsNegative(p);
|
|
129
|
+
|
|
130
|
+
mpz_set_ui(m, 0);
|
|
131
|
+
for (i = 0; i < size; i++) {
|
|
132
|
+
mpz_set_ui(temp, PythonLongVal(p)[i]);
|
|
133
|
+
mpz_mul_2exp(temp2, temp, PyLong_SHIFT * i);
|
|
134
|
+
mpz_add(m, m, temp2);
|
|
135
|
+
}
|
|
136
|
+
mpz_clear(temp);
|
|
137
|
+
mpz_clear(temp2);
|
|
138
|
+
Py_XDECREF(p);
|
|
139
|
+
if(isNeg) mpz_neg(m, m);
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
//void longObjToBN(BIGNUM *m, PyObject *o) {
|
|
143
|
+
// PyLongObject *p = (PyLongObject *) PyNumber_Long(o);
|
|
144
|
+
// int size, i, tmp = Py_SIZE(p);
|
|
145
|
+
// BIGNUM *temp = BN_new(), *temp2 = BN_new();
|
|
146
|
+
// BN_init(temp);
|
|
147
|
+
// BN_init(temp2);
|
|
148
|
+
// if (tmp > 0)
|
|
149
|
+
// size = tmp;
|
|
150
|
+
// else
|
|
151
|
+
// size = -tmp;
|
|
152
|
+
// BN_zero(m, 0);
|
|
153
|
+
// for (i = 0; i < size; i++) {
|
|
154
|
+
// BN_set_word(temp, p->long_value.ob_digit[i]);
|
|
155
|
+
// mpz_mul_2exp(temp2, temp, PyLong_SHIFT * i);
|
|
156
|
+
// mpz_add(m, m, temp2);
|
|
157
|
+
// }
|
|
158
|
+
// mpz_clear(temp);
|
|
159
|
+
// mpz_clear(temp2);
|
|
160
|
+
//}
|
|
161
|
+
|
|
162
|
+
PyObject *bnToLongObj(BIGNUM *m) {
|
|
163
|
+
return PyLong_FromString(BN_bn2hex(m), NULL, 16);
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
int bnToMPZ(BIGNUM *p, mpz_t m) {
|
|
167
|
+
size_t count = BN_num_bytes(p);
|
|
168
|
+
unsigned char* tmp = malloc(count);
|
|
169
|
+
if(!tmp) {
|
|
170
|
+
return FALSE;
|
|
171
|
+
}
|
|
172
|
+
BN_bn2bin(p, tmp);
|
|
173
|
+
mpz_import(m, count, 1, 1, 0, 0, tmp);
|
|
174
|
+
if(BN_is_negative(p)) {
|
|
175
|
+
mpz_neg(m, m);
|
|
176
|
+
}
|
|
177
|
+
free(tmp);
|
|
178
|
+
|
|
179
|
+
return TRUE;
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
// generate a BN from an mpz_t type
|
|
183
|
+
int mpzToBN(mpz_t m, BIGNUM *b) {
|
|
184
|
+
void (*freefunc) (void *, size_t);
|
|
185
|
+
mp_get_memory_functions (NULL, NULL, &freefunc);
|
|
186
|
+
|
|
187
|
+
size_t count;
|
|
188
|
+
unsigned char* bytes = mpz_export (NULL, &count, 1, 1, 0, 0, m);
|
|
189
|
+
BN_bin2bn(bytes, count, b);
|
|
190
|
+
freefunc(bytes, count);
|
|
191
|
+
|
|
192
|
+
debug("Original input m => ");
|
|
193
|
+
print_mpz(m, 10);
|
|
194
|
+
debug("GMP num bits => '%i'\n", GMP_NUMB_BITS);
|
|
195
|
+
debug("BN num bits => '%i'\n", BN_BITS2);
|
|
196
|
+
return TRUE;
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
PyObject *mpzToLongObj(mpz_t m) {
|
|
200
|
+
/* borrowed from gmpy */
|
|
201
|
+
int size = (mpz_sizeinbase(m, 2) + PyLong_SHIFT - 1) / PyLong_SHIFT;
|
|
202
|
+
int i, isNeg = (mpz_sgn(m) < 0) ? TRUE : FALSE;
|
|
203
|
+
mpz_t temp;
|
|
204
|
+
PyLongObject *l = _PyLong_New(size);
|
|
205
|
+
if (!l)
|
|
206
|
+
return NULL;
|
|
207
|
+
mpz_init_set(temp, m);
|
|
208
|
+
/* Work with absolute value for digit extraction.
|
|
209
|
+
* mpz_fdiv_q_2exp does floor division, which gives incorrect results
|
|
210
|
+
* for negative numbers (e.g., -5 / 2 = -3 with floor, not -2).
|
|
211
|
+
* By using the absolute value, we extract digits correctly and
|
|
212
|
+
* apply the sign at the end. */
|
|
213
|
+
if (isNeg) {
|
|
214
|
+
mpz_abs(temp, temp);
|
|
215
|
+
}
|
|
216
|
+
for (i = 0; i < size; i++) {
|
|
217
|
+
PythonLongVal(l)[i] = (digit)(mpz_get_ui(temp) & PyLong_MASK);
|
|
218
|
+
mpz_fdiv_q_2exp(temp, temp, PyLong_SHIFT);
|
|
219
|
+
}
|
|
220
|
+
/* Normalize: remove leading zeros */
|
|
221
|
+
i = size;
|
|
222
|
+
while ((i > 0) && (PythonLongVal(l)[i - 1] == 0))
|
|
223
|
+
i--;
|
|
224
|
+
/* Set the size/sign using the appropriate method for the Python version */
|
|
225
|
+
#if PY_MINOR_VERSION >= 12
|
|
226
|
+
/* Python 3.12+: Set lv_tag with sign and digit count */
|
|
227
|
+
int sign = isNeg ? -1 : (i == 0 ? 0 : 1);
|
|
228
|
+
PythonLongSetTag(l, sign, i);
|
|
229
|
+
#else
|
|
230
|
+
/* Python 3.11-: Set ob_size (negative for negative numbers) */
|
|
231
|
+
if(isNeg) {
|
|
232
|
+
PYTHON_SET_SIZE(l, -i);
|
|
233
|
+
}
|
|
234
|
+
else {
|
|
235
|
+
PYTHON_SET_SIZE(l, i);
|
|
236
|
+
}
|
|
237
|
+
#endif
|
|
238
|
+
mpz_clear(temp);
|
|
239
|
+
return (PyObject *) l;
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
void print_mpz(mpz_t x, int base) {
|
|
243
|
+
#ifdef DEBUG
|
|
244
|
+
if(base <= 2 || base > 64) return;
|
|
245
|
+
size_t x_size = mpz_sizeinbase(x, base) + 2;
|
|
246
|
+
char *x_str = (char *) malloc(x_size);
|
|
247
|
+
if (x_str == NULL) return;
|
|
248
|
+
x_str = mpz_get_str(x_str, base, x);
|
|
249
|
+
debug("Element => '%s'\n", x_str);
|
|
250
|
+
debug("Order of Element => '%zd'\n", x_size);
|
|
251
|
+
free(x_str);
|
|
252
|
+
#endif
|
|
253
|
+
}
|
|
254
|
+
|
|
255
|
+
void print_bn_dec(const BIGNUM *bn) {
|
|
256
|
+
#ifdef DEBUG
|
|
257
|
+
printf("BIGNUM *bn => ");
|
|
258
|
+
char *pstr = BN_bn2dec(bn);
|
|
259
|
+
printf("%s\n", pstr);
|
|
260
|
+
OPENSSL_free(pstr);
|
|
261
|
+
#endif
|
|
262
|
+
}
|
|
263
|
+
|
|
264
|
+
void printf_buffer_as_hex(uint8_t *data, size_t len) {
|
|
265
|
+
#ifdef DEBUG
|
|
266
|
+
size_t i;
|
|
267
|
+
|
|
268
|
+
for (i = 0; i < len; i++) {
|
|
269
|
+
printf("%02x ", data[i]);
|
|
270
|
+
}
|
|
271
|
+
printf("\n");
|
|
272
|
+
#endif
|
|
273
|
+
}
|
|
274
|
+
|
|
275
|
+
/*!
|
|
276
|
+
* Hash a null-terminated string to a byte array.
|
|
277
|
+
*
|
|
278
|
+
* @param input_buf The input buffer.
|
|
279
|
+
* @param input_len The input buffer length (in bytes).
|
|
280
|
+
* @param output_buf A pre-allocated output buffer of size hash_len.
|
|
281
|
+
* @param hash_len Length of the output hash (in bytes). Should be approximately bit size of curve group order.
|
|
282
|
+
* @param hash_prefix prefix for hash function.
|
|
283
|
+
*/
|
|
284
|
+
int hash_to_bytes(uint8_t *input_buf, int input_len, uint8_t *output_buf, int hash_len, uint8_t hash_prefix)
|
|
285
|
+
{
|
|
286
|
+
EVP_MD_CTX *ctx = NULL;
|
|
287
|
+
unsigned int md_len = 0;
|
|
288
|
+
int i, new_input_len = input_len + 2; // extra byte for prefix
|
|
289
|
+
uint8_t first_block = 0;
|
|
290
|
+
uint8_t new_input[new_input_len+1];
|
|
291
|
+
|
|
292
|
+
memset(new_input, 0, new_input_len+1);
|
|
293
|
+
new_input[0] = first_block; // block number (always 0 by default)
|
|
294
|
+
new_input[1] = hash_prefix; // set hash prefix
|
|
295
|
+
memcpy((uint8_t *)(new_input+2), input_buf, input_len); // copy input bytes
|
|
296
|
+
|
|
297
|
+
debug("new input => \n");
|
|
298
|
+
printf_buffer_as_hex(new_input, new_input_len);
|
|
299
|
+
// prepare output buf
|
|
300
|
+
memset(output_buf, 0, hash_len);
|
|
301
|
+
|
|
302
|
+
ctx = EVP_MD_CTX_new();
|
|
303
|
+
if (ctx == NULL) return FALSE;
|
|
304
|
+
|
|
305
|
+
if (hash_len <= HASH_LEN) {
|
|
306
|
+
EVP_DigestInit_ex(ctx, EVP_sha256(), NULL);
|
|
307
|
+
EVP_DigestUpdate(ctx, new_input, new_input_len);
|
|
308
|
+
uint8_t md[HASH_LEN+1];
|
|
309
|
+
EVP_DigestFinal_ex(ctx, md, &md_len);
|
|
310
|
+
memcpy(output_buf, md, hash_len);
|
|
311
|
+
}
|
|
312
|
+
else {
|
|
313
|
+
// apply variable-size hash technique to get desired size
|
|
314
|
+
// determine block count.
|
|
315
|
+
int blocks = (int) ceil(((double) hash_len) / HASH_LEN);
|
|
316
|
+
debug("Num blocks needed: %d\n", blocks);
|
|
317
|
+
uint8_t md[HASH_LEN+1];
|
|
318
|
+
uint8_t md2[(blocks * HASH_LEN)+1];
|
|
319
|
+
uint8_t *target_buf = md2;
|
|
320
|
+
for(i = 0; i < blocks; i++) {
|
|
321
|
+
/* compute digest = SHA-2( i || prefix || input_buf ) || ... || SHA-2( n-1 || prefix || input_buf ) */
|
|
322
|
+
target_buf += (i * HASH_LEN);
|
|
323
|
+
new_input[0] = (uint8_t) i;
|
|
324
|
+
EVP_DigestInit_ex(ctx, EVP_sha256(), NULL);
|
|
325
|
+
debug("input %d => ", i);
|
|
326
|
+
printf_buffer_as_hex(new_input, new_input_len);
|
|
327
|
+
EVP_DigestUpdate(ctx, new_input, new_input_len);
|
|
328
|
+
EVP_DigestFinal_ex(ctx, md, &md_len);
|
|
329
|
+
memcpy(target_buf, md, hash_len);
|
|
330
|
+
debug("block %d => ", i);
|
|
331
|
+
printf_buffer_as_hex(md, HASH_LEN);
|
|
332
|
+
memset(md, 0, HASH_LEN);
|
|
333
|
+
}
|
|
334
|
+
// copy back to caller
|
|
335
|
+
memcpy(output_buf, md2, hash_len);
|
|
336
|
+
}
|
|
337
|
+
|
|
338
|
+
EVP_MD_CTX_free(ctx);
|
|
339
|
+
return TRUE;
|
|
340
|
+
}
|
|
341
|
+
|
|
342
|
+
|
|
343
|
+
int hash_to_group_element(mpz_t x, int block_num, uint8_t *output_buf) {
|
|
344
|
+
|
|
345
|
+
size_t count = 0;
|
|
346
|
+
uint8_t *rop_buf = (uint8_t *) mpz_export(NULL, &count, 1, sizeof(char), 0,
|
|
347
|
+
0, x);
|
|
348
|
+
|
|
349
|
+
debug("rop_buf...\n");
|
|
350
|
+
printf_buffer_as_hex(rop_buf, count);
|
|
351
|
+
// create another buffer with block_num and rop_buf as input. Maybe use snprintf?
|
|
352
|
+
if (block_num > 0) {
|
|
353
|
+
int len = count + sizeof(uint32_t);
|
|
354
|
+
uint8_t *tmp_buf = (uint8_t *) malloc(len + 1);
|
|
355
|
+
if (tmp_buf == NULL) return FALSE;
|
|
356
|
+
memset(tmp_buf, 0, len);
|
|
357
|
+
// sprintf(tmp_buf, "%d%s", block_num, (char *) rop_buf);
|
|
358
|
+
uint32_t block_str = (uint32_t) block_num;
|
|
359
|
+
*((uint32_t*) tmp_buf) = block_str;
|
|
360
|
+
strncat((char *) (tmp_buf + sizeof(uint32_t)), (const char *) rop_buf,
|
|
361
|
+
count);
|
|
362
|
+
|
|
363
|
+
debug("tmp_buf after strcat...\n");
|
|
364
|
+
printf_buffer_as_hex(tmp_buf, len);
|
|
365
|
+
|
|
366
|
+
hash_to_bytes(tmp_buf, len, output_buf, HASH_LEN,
|
|
367
|
+
HASH_FUNCTION_KEM_DERIVE);
|
|
368
|
+
free(tmp_buf);
|
|
369
|
+
} else {
|
|
370
|
+
hash_to_bytes(rop_buf, (int) count, output_buf, HASH_LEN,
|
|
371
|
+
HASH_FUNCTION_KEM_DERIVE);
|
|
372
|
+
}
|
|
373
|
+
|
|
374
|
+
free(rop_buf);
|
|
375
|
+
return TRUE;
|
|
376
|
+
}
|
|
377
|
+
|
|
378
|
+
void _reduce(Integer *object) {
|
|
379
|
+
if (object != NULL && mpz_sgn(object->m) > 0)
|
|
380
|
+
mpz_mod(object->e, object->e, object->m);
|
|
381
|
+
}
|
|
382
|
+
|
|
383
|
+
void Integer_dealloc(Integer* self) {
|
|
384
|
+
/* clear structure */
|
|
385
|
+
mpz_clear(self->m);
|
|
386
|
+
mpz_clear(self->e);
|
|
387
|
+
Py_TYPE(self)->tp_free((PyObject*) self);
|
|
388
|
+
}
|
|
389
|
+
|
|
390
|
+
PyObject *Integer_new(PyTypeObject *type, PyObject *args, PyObject *kwds) {
|
|
391
|
+
Integer *self;
|
|
392
|
+
|
|
393
|
+
self = (Integer *) type->tp_alloc(type, 0);
|
|
394
|
+
if (self != NULL) {
|
|
395
|
+
/* initialize fields here */
|
|
396
|
+
mpz_init(self->e);
|
|
397
|
+
mpz_init(self->m);
|
|
398
|
+
self->initialized = TRUE;
|
|
399
|
+
}
|
|
400
|
+
return (PyObject *) self;
|
|
401
|
+
}
|
|
402
|
+
|
|
403
|
+
int Integer_init(Integer *self, PyObject *args, PyObject *kwds) {
|
|
404
|
+
PyObject *num = NULL, *mod = NULL;
|
|
405
|
+
static char *kwlist[] = { "number", "modulus", NULL };
|
|
406
|
+
|
|
407
|
+
if (!PyArg_ParseTupleAndKeywords(args, kwds, "O|O", kwlist, &num, &mod)) {
|
|
408
|
+
return -1;
|
|
409
|
+
}
|
|
410
|
+
|
|
411
|
+
// check if they are of type long
|
|
412
|
+
if(PyInteger_Check(num)) {
|
|
413
|
+
Integer *num1 = (Integer *) num;
|
|
414
|
+
mpz_set(self->e, num1->e);
|
|
415
|
+
}
|
|
416
|
+
else if(_PyLong_Check(num)) {
|
|
417
|
+
longObjToMPZ(self->e, num);
|
|
418
|
+
}
|
|
419
|
+
// raise error
|
|
420
|
+
else if (PyBytes_Check(num)) {
|
|
421
|
+
// convert directly to a char string of bytes
|
|
422
|
+
char *bytes = PyBytes_AS_STRING(num);
|
|
423
|
+
int bytes_len = strlen(bytes);
|
|
424
|
+
mpz_import(self->e, bytes_len, 1, sizeof(bytes[0]), 0, 0, bytes);
|
|
425
|
+
} else if (PyUnicode_Check(num)) {
|
|
426
|
+
// cast to a bytes object, then interpret as a string of bytes
|
|
427
|
+
PyObject *_num = PyUnicode_AsUTF8String(num);
|
|
428
|
+
const char *bytes = PyBytes_AS_STRING(_num);
|
|
429
|
+
int bytes_len = strlen(bytes);
|
|
430
|
+
mpz_import(self->e, bytes_len, 1, sizeof(bytes[0]), 0, 0, bytes);
|
|
431
|
+
Py_DECREF(_num);
|
|
432
|
+
} else {
|
|
433
|
+
return -1;
|
|
434
|
+
}
|
|
435
|
+
|
|
436
|
+
if (mod != NULL) {
|
|
437
|
+
if (_PyLong_Check(mod)) {
|
|
438
|
+
mpz_t m;
|
|
439
|
+
mpz_init(m);
|
|
440
|
+
longObjToMPZ(m, mod);
|
|
441
|
+
if(mpz_sgn(m) > 0) mpz_set(self->m, m);
|
|
442
|
+
else {
|
|
443
|
+
mpz_clear(m);
|
|
444
|
+
PyErr_SetString(IntegerError, "negative modulus not allowed.");
|
|
445
|
+
return -1;
|
|
446
|
+
}
|
|
447
|
+
mpz_clear(m);
|
|
448
|
+
}
|
|
449
|
+
else if(PyInteger_Check(mod)) {
|
|
450
|
+
Integer *mod1 = (Integer *) mod;
|
|
451
|
+
mpz_set(self->m, mod1->e);
|
|
452
|
+
}
|
|
453
|
+
else {
|
|
454
|
+
PyErr_SetString(IntegerError, "invalid type for modulus");
|
|
455
|
+
return -1;
|
|
456
|
+
}
|
|
457
|
+
}
|
|
458
|
+
// else leave self->m set to 0.
|
|
459
|
+
return 0;
|
|
460
|
+
}
|
|
461
|
+
|
|
462
|
+
static PyObject *Integer_equals(PyObject *o1, PyObject *o2, int opid) {
|
|
463
|
+
Integer *lhs = NULL, *rhs = NULL;
|
|
464
|
+
int foundLHS = FALSE, foundRHS = FALSE, result = -1, errorOccured = FALSE;
|
|
465
|
+
mpz_t lhs_mpz, rhs_mpz, l, r;
|
|
466
|
+
mpz_init(lhs_mpz);
|
|
467
|
+
mpz_init(rhs_mpz);
|
|
468
|
+
|
|
469
|
+
Convert_Types(o1, o2, lhs, rhs, foundLHS, foundRHS, lhs_mpz, rhs_mpz, errorOccured);
|
|
470
|
+
// perform operation
|
|
471
|
+
if(errorOccured) {
|
|
472
|
+
mpz_clear(lhs_mpz);
|
|
473
|
+
mpz_clear(rhs_mpz);
|
|
474
|
+
ErrorMsg("invalid left or right operand type.");
|
|
475
|
+
}
|
|
476
|
+
else if (foundLHS) {
|
|
477
|
+
debug("foundLHS\n");
|
|
478
|
+
if (mpz_sgn(rhs->m) == 0) {
|
|
479
|
+
result = mpz_cmp(lhs_mpz, rhs->e);
|
|
480
|
+
} else {
|
|
481
|
+
mpz_init(r);
|
|
482
|
+
mpz_mod(r, rhs->e, rhs->m);
|
|
483
|
+
result = mpz_cmp(r, lhs_mpz);
|
|
484
|
+
mpz_clear(r);
|
|
485
|
+
}
|
|
486
|
+
} else if (foundRHS) {
|
|
487
|
+
debug("foundRHS!\n");
|
|
488
|
+
|
|
489
|
+
if (mpz_sgn(lhs->m) == 0) {
|
|
490
|
+
result = mpz_cmp(lhs->e, rhs_mpz);
|
|
491
|
+
} else {
|
|
492
|
+
mpz_init(l);
|
|
493
|
+
mpz_mod(l, lhs->e, lhs->m);
|
|
494
|
+
result = mpz_cmp(l, rhs_mpz);
|
|
495
|
+
mpz_clear(l);
|
|
496
|
+
}
|
|
497
|
+
} else {
|
|
498
|
+
debug("Modulus equal? %d =?= 0\n", mpz_cmp(lhs->m, rhs->m));
|
|
499
|
+
if (mpz_sgn(lhs->m) == 0 && mpz_sgn(rhs->m) == 0) {
|
|
500
|
+
// comparing ints without a modulous
|
|
501
|
+
result = mpz_cmp(lhs->e, rhs->e);
|
|
502
|
+
}
|
|
503
|
+
else if (mpz_cmp(lhs->m, rhs->m) == 0) {
|
|
504
|
+
// comparing ints with a modolus that are equal
|
|
505
|
+
mpz_init(l);
|
|
506
|
+
mpz_init(r);
|
|
507
|
+
mpz_mod(l, lhs->e, lhs->m);
|
|
508
|
+
mpz_mod(r, rhs->e, rhs->m);
|
|
509
|
+
result = mpz_cmp(l, r);
|
|
510
|
+
mpz_clear(l);
|
|
511
|
+
mpz_clear(r);
|
|
512
|
+
}
|
|
513
|
+
else {
|
|
514
|
+
mpz_clear(lhs_mpz);
|
|
515
|
+
mpz_clear(rhs_mpz);
|
|
516
|
+
ErrorMsg("cannot compare integers with different modulus.");
|
|
517
|
+
}
|
|
518
|
+
}
|
|
519
|
+
mpz_clear(lhs_mpz);
|
|
520
|
+
mpz_clear(rhs_mpz);
|
|
521
|
+
|
|
522
|
+
if(opid == Py_EQ) {
|
|
523
|
+
if(result == 0) Py_RETURN_TRUE;
|
|
524
|
+
else Py_RETURN_FALSE;
|
|
525
|
+
}
|
|
526
|
+
else if(opid == Py_NE) { /* Py_NE */
|
|
527
|
+
if(result != 0) Py_RETURN_TRUE;
|
|
528
|
+
else Py_RETURN_FALSE;
|
|
529
|
+
}
|
|
530
|
+
else if(opid == Py_LT) {
|
|
531
|
+
if(result < 0) Py_RETURN_TRUE;
|
|
532
|
+
else Py_RETURN_FALSE;
|
|
533
|
+
}
|
|
534
|
+
else if(opid == Py_LE) {
|
|
535
|
+
if(result <= 0) Py_RETURN_TRUE;
|
|
536
|
+
else Py_RETURN_FALSE;
|
|
537
|
+
}
|
|
538
|
+
else if(opid == Py_GT) {
|
|
539
|
+
if(result > 0) Py_RETURN_TRUE;
|
|
540
|
+
else Py_RETURN_FALSE;
|
|
541
|
+
}
|
|
542
|
+
else if(opid == Py_GE) {
|
|
543
|
+
if(result >= 0) Py_RETURN_TRUE;
|
|
544
|
+
else Py_RETURN_FALSE;
|
|
545
|
+
}
|
|
546
|
+
|
|
547
|
+
ErrorMsg("unexpected comparison operator.");
|
|
548
|
+
}
|
|
549
|
+
|
|
550
|
+
PyObject *Integer_print(Integer *self) {
|
|
551
|
+
PyObject *strObject = NULL;
|
|
552
|
+
if (self->initialized) {
|
|
553
|
+
size_t e_size = mpz_sizeinbase(self->e, 10) + 2;
|
|
554
|
+
char *e_str = (char *) malloc(e_size);
|
|
555
|
+
if (e_str == NULL) return NULL;
|
|
556
|
+
mpz_get_str(e_str, 10, self->e);
|
|
557
|
+
|
|
558
|
+
if (mpz_sgn(self->m) != 0) {
|
|
559
|
+
size_t m_size = mpz_sizeinbase(self->m, 10) + 2;
|
|
560
|
+
char *m_str = (char *) malloc(m_size);
|
|
561
|
+
if (m_str == NULL) {
|
|
562
|
+
free(e_str);
|
|
563
|
+
return NULL;
|
|
564
|
+
}
|
|
565
|
+
mpz_get_str(m_str, 10, self->m);
|
|
566
|
+
strObject = PyUnicode_FromFormat("%s mod %s", (const char *) e_str,
|
|
567
|
+
(const char *) m_str);
|
|
568
|
+
free(m_str);
|
|
569
|
+
} else {
|
|
570
|
+
strObject = PyUnicode_FromFormat("%s", (const char *) e_str);
|
|
571
|
+
}
|
|
572
|
+
free(e_str);
|
|
573
|
+
return strObject;
|
|
574
|
+
}
|
|
575
|
+
//
|
|
576
|
+
// if (self->state_init) {
|
|
577
|
+
// return PyUnicode_FromString("");
|
|
578
|
+
// }
|
|
579
|
+
|
|
580
|
+
PyErr_SetString(IntegerError, "invalid integer object.");
|
|
581
|
+
return NULL;
|
|
582
|
+
}
|
|
583
|
+
|
|
584
|
+
Integer *createNewInteger() {
|
|
585
|
+
Integer *newObject = PyObject_New(Integer, &IntegerType);
|
|
586
|
+
//mpz_init(newObject->e);
|
|
587
|
+
//mpz_init_set(newObject->m, m);
|
|
588
|
+
newObject->initialized = TRUE;
|
|
589
|
+
return newObject;
|
|
590
|
+
}
|
|
591
|
+
|
|
592
|
+
//Integer *createNewIntegerNoMod(void) {
|
|
593
|
+
// Integer *newObject = PyObject_New(Integer, &IntegerType);
|
|
594
|
+
//
|
|
595
|
+
// //mpz_init(newObject->e);
|
|
596
|
+
// //mpz_init(newObject->m);
|
|
597
|
+
// newObject->initialized = TRUE;
|
|
598
|
+
//
|
|
599
|
+
// return newObject;
|
|
600
|
+
//}
|
|
601
|
+
|
|
602
|
+
static PyObject *Integer_set(Integer *self, PyObject *args) {
|
|
603
|
+
PyObject *obj = NULL;
|
|
604
|
+
Integer *intObj = NULL;
|
|
605
|
+
|
|
606
|
+
if (PyArg_ParseTuple(args, "O", &obj)) {
|
|
607
|
+
|
|
608
|
+
if (PyInteger_Check(obj)) {
|
|
609
|
+
intObj = (Integer *) obj;
|
|
610
|
+
self->initialized = TRUE;
|
|
611
|
+
mpz_set(self->e, intObj->e);
|
|
612
|
+
mpz_set(self->m, intObj->m);
|
|
613
|
+
return Py_BuildValue("i", TRUE);
|
|
614
|
+
}
|
|
615
|
+
}
|
|
616
|
+
|
|
617
|
+
return Py_BuildValue("i", FALSE);
|
|
618
|
+
}
|
|
619
|
+
|
|
620
|
+
static PyObject *Integer_add(PyObject *o1, PyObject *o2) {
|
|
621
|
+
// determine type of each side
|
|
622
|
+
Integer *lhs = NULL, *rhs = NULL, *rop = NULL;
|
|
623
|
+
int foundLHS = FALSE, foundRHS = FALSE, errorOccured = FALSE;
|
|
624
|
+
mpz_t lhs_mpz, rhs_mpz;
|
|
625
|
+
mpz_init(lhs_mpz);
|
|
626
|
+
mpz_init(rhs_mpz);
|
|
627
|
+
|
|
628
|
+
Convert_Types(o1, o2, lhs, rhs, foundLHS, foundRHS, lhs_mpz, rhs_mpz, errorOccured);
|
|
629
|
+
// perform operation
|
|
630
|
+
if(errorOccured) {
|
|
631
|
+
mpz_clear(lhs_mpz);
|
|
632
|
+
mpz_clear(rhs_mpz);
|
|
633
|
+
ErrorMsg("invalid left or right operand type.");
|
|
634
|
+
}
|
|
635
|
+
else if (foundLHS) {
|
|
636
|
+
//debug("foundLHS\n");
|
|
637
|
+
if(mpz_sgn(rhs->m) == 0) { // mpz_sgn(lhs_mpz) > 0
|
|
638
|
+
rop = createNewInteger();
|
|
639
|
+
mpz_init(rop->e);
|
|
640
|
+
mpz_init(rop->m);
|
|
641
|
+
mpz_add(rop->e, lhs_mpz, rhs->e);
|
|
642
|
+
}
|
|
643
|
+
else {
|
|
644
|
+
// operation: a + b % n = c... no longer allowed
|
|
645
|
+
ErrorMsg("unsupported operation.");
|
|
646
|
+
}
|
|
647
|
+
} else if (foundRHS) {
|
|
648
|
+
// debug("foundRHS!\n");
|
|
649
|
+
if(mpz_sgn(lhs->m) == 0) {
|
|
650
|
+
rop = createNewInteger();
|
|
651
|
+
mpz_init(rop->e);
|
|
652
|
+
mpz_init(rop->m);
|
|
653
|
+
mpz_add(rop->e, lhs->e, rhs_mpz);
|
|
654
|
+
}
|
|
655
|
+
else {
|
|
656
|
+
// operation: a % n + b ... are no longer allowed
|
|
657
|
+
ErrorMsg("unsupported operation.");
|
|
658
|
+
}
|
|
659
|
+
} else {
|
|
660
|
+
// debug("Modulus equal? %d =?= 0\n", mpz_cmp(lhs->m, rhs->m));
|
|
661
|
+
if (mpz_cmp(lhs->m, rhs->m) == 0) {
|
|
662
|
+
rop = createNewInteger();
|
|
663
|
+
mpz_init(rop->e);
|
|
664
|
+
mpz_init_set(rop->m, lhs->m);
|
|
665
|
+
mpz_add(rop->e, lhs->e, rhs->e);
|
|
666
|
+
} else {
|
|
667
|
+
EXIT_IF(TRUE, "cannot add integers with different modulus.");
|
|
668
|
+
}
|
|
669
|
+
}
|
|
670
|
+
|
|
671
|
+
// if(mpz_sgn(rop->e) < 0 || mpz_cmp(rop->e, rop->m) > 0) {
|
|
672
|
+
// _reduce(rop);
|
|
673
|
+
// }
|
|
674
|
+
|
|
675
|
+
#ifdef BENCHMARK_ENABLED
|
|
676
|
+
UPDATE_BENCHMARK(ADDITION, tmpBench);
|
|
677
|
+
#endif
|
|
678
|
+
return (PyObject *) rop;
|
|
679
|
+
}
|
|
680
|
+
|
|
681
|
+
static PyObject *Integer_sub(PyObject *o1, PyObject *o2) {
|
|
682
|
+
// determine type of each side
|
|
683
|
+
Integer *lhs = NULL, *rhs = NULL, *rop = NULL;
|
|
684
|
+
int foundLHS = FALSE, foundRHS = FALSE, errorOccured = FALSE;
|
|
685
|
+
mpz_t lhs_mpz, rhs_mpz;
|
|
686
|
+
mpz_init(lhs_mpz);
|
|
687
|
+
mpz_init(rhs_mpz);
|
|
688
|
+
|
|
689
|
+
Convert_Types(o1, o2, lhs, rhs, foundLHS, foundRHS, lhs_mpz, rhs_mpz, errorOccured);
|
|
690
|
+
// perform operation
|
|
691
|
+
if(errorOccured) {
|
|
692
|
+
mpz_clear(lhs_mpz);
|
|
693
|
+
mpz_clear(rhs_mpz);
|
|
694
|
+
ErrorMsg("invalid left or right operand type.");
|
|
695
|
+
}
|
|
696
|
+
else if (foundLHS) {
|
|
697
|
+
// debug("foundLHS\n");
|
|
698
|
+
if(mpz_sgn(rhs->m) == 0) { // mpz_sgn(lhs_mpz) > 0
|
|
699
|
+
rop = createNewInteger();
|
|
700
|
+
mpz_init(rop->e);
|
|
701
|
+
mpz_init(rop->m);
|
|
702
|
+
mpz_sub(rop->e, lhs_mpz, rhs->e);
|
|
703
|
+
}
|
|
704
|
+
else {
|
|
705
|
+
// operation: a - b % n = c... no longer allowed
|
|
706
|
+
ErrorMsg("unsupported operation.");
|
|
707
|
+
}
|
|
708
|
+
} else if (foundRHS) {
|
|
709
|
+
// debug("foundRHS!\n");
|
|
710
|
+
if(mpz_sgn(lhs->m) == 0) {
|
|
711
|
+
rop = createNewInteger();
|
|
712
|
+
mpz_init(rop->e);
|
|
713
|
+
mpz_init(rop->m);
|
|
714
|
+
mpz_sub(rop->e, lhs->e, rhs_mpz);
|
|
715
|
+
}
|
|
716
|
+
else {
|
|
717
|
+
// operation: a % n - b ... are no longer allowed
|
|
718
|
+
ErrorMsg("unsupported operation.");
|
|
719
|
+
}
|
|
720
|
+
} else {
|
|
721
|
+
// debug("Modulus equal? %d =?= 0\n", mpz_cmp(lhs->m, rhs->m));
|
|
722
|
+
if (mpz_cmp(lhs->m, rhs->m) == 0) {
|
|
723
|
+
rop = createNewInteger();
|
|
724
|
+
mpz_init(rop->e);
|
|
725
|
+
mpz_init_set(rop->m, lhs->m);
|
|
726
|
+
mpz_sub(rop->e, lhs->e, rhs->e);
|
|
727
|
+
} else {
|
|
728
|
+
EXIT_IF(TRUE,"cannot subtract integers with different modulus.");
|
|
729
|
+
}
|
|
730
|
+
}
|
|
731
|
+
|
|
732
|
+
mpz_clear(lhs_mpz);
|
|
733
|
+
mpz_clear(rhs_mpz);
|
|
734
|
+
if(mpz_sgn(rop->e) < 0) {
|
|
735
|
+
mpz_add(rop->e, rop->e, rop->m);
|
|
736
|
+
}
|
|
737
|
+
#ifdef BENCHMARK_ENABLED
|
|
738
|
+
UPDATE_BENCHMARK(SUBTRACTION, tmpBench);
|
|
739
|
+
#endif
|
|
740
|
+
return (PyObject *) rop;
|
|
741
|
+
}
|
|
742
|
+
|
|
743
|
+
static PyObject *Integer_mul(PyObject *o1, PyObject *o2) {
|
|
744
|
+
// determine type of each side
|
|
745
|
+
Integer *lhs = NULL, *rhs = NULL, *rop = NULL;
|
|
746
|
+
int foundLHS = FALSE, foundRHS = FALSE, errorOccured = FALSE;
|
|
747
|
+
// long lhs_value = 0, rhs_value = 0;
|
|
748
|
+
mpz_t lhs_mpz, rhs_mpz;
|
|
749
|
+
mpz_init(lhs_mpz);
|
|
750
|
+
mpz_init(rhs_mpz);
|
|
751
|
+
|
|
752
|
+
Convert_Types(o1, o2, lhs, rhs, foundLHS, foundRHS, lhs_mpz, rhs_mpz, errorOccured);
|
|
753
|
+
// perform operation
|
|
754
|
+
if(errorOccured) {
|
|
755
|
+
mpz_clear(lhs_mpz);
|
|
756
|
+
mpz_clear(rhs_mpz);
|
|
757
|
+
ErrorMsg("invalid left or right operand type.");
|
|
758
|
+
}
|
|
759
|
+
else if (foundLHS) {
|
|
760
|
+
//debug("foundLHS\n");
|
|
761
|
+
if(mpz_sgn(rhs->m) == 0) { // mpz_sgn(lhs_mpz) > 0
|
|
762
|
+
rop = createNewInteger();
|
|
763
|
+
mpz_init(rop->e);
|
|
764
|
+
mpz_init(rop->m);
|
|
765
|
+
mpz_mul(rop->e, lhs_mpz, rhs->e);
|
|
766
|
+
}
|
|
767
|
+
else {
|
|
768
|
+
// operation: a * b % n = c... no longer allowed
|
|
769
|
+
ErrorMsg("unsupported operation.");
|
|
770
|
+
}
|
|
771
|
+
} else if (foundRHS) {
|
|
772
|
+
// debug("foundRHS!\n");
|
|
773
|
+
if(mpz_sgn(lhs->m) == 0) {
|
|
774
|
+
rop = createNewInteger();
|
|
775
|
+
mpz_init(rop->e);
|
|
776
|
+
mpz_init(rop->m);
|
|
777
|
+
mpz_mul(rop->e, lhs->e, rhs_mpz);
|
|
778
|
+
}
|
|
779
|
+
else {
|
|
780
|
+
// operation: a % n * b ... are no longer allowed
|
|
781
|
+
ErrorMsg("unsupported operation.");
|
|
782
|
+
}
|
|
783
|
+
} else {
|
|
784
|
+
// debug("Modulus equal? %d =?= 0\n", mpz_cmp(lhs->m, rhs->m));
|
|
785
|
+
// if modulus is equal
|
|
786
|
+
if (mpz_cmp(lhs->m, rhs->m) == 0) {
|
|
787
|
+
// compute ((lhs % m) * (rhs % m)) % m (reduce before)
|
|
788
|
+
rop = createNewInteger();
|
|
789
|
+
mpz_init_set(rop->e, lhs->e);
|
|
790
|
+
mpz_init_set(rop->m, lhs->m);
|
|
791
|
+
mpz_mul(rop->e, rop->e, rhs->e);
|
|
792
|
+
}
|
|
793
|
+
else {
|
|
794
|
+
EXIT_IF(TRUE, "invalid operation - integers with different or no modulus.");
|
|
795
|
+
}
|
|
796
|
+
}
|
|
797
|
+
|
|
798
|
+
mpz_clear(lhs_mpz);
|
|
799
|
+
mpz_clear(rhs_mpz);
|
|
800
|
+
// _reduce(rop);
|
|
801
|
+
#ifdef BENCHMARK_ENABLED
|
|
802
|
+
UPDATE_BENCHMARK(MULTIPLICATION, tmpBench);
|
|
803
|
+
#endif
|
|
804
|
+
return (PyObject *) rop;
|
|
805
|
+
}
|
|
806
|
+
|
|
807
|
+
static PyObject *Integer_invert(PyObject *o1) {
|
|
808
|
+
Integer *base = NULL, *rop = NULL;
|
|
809
|
+
if (PyInteger_Check(o1)) {
|
|
810
|
+
// let's try to compute inverse
|
|
811
|
+
base = (Integer *) o1;
|
|
812
|
+
if (base->initialized) {
|
|
813
|
+
rop = createNewInteger();
|
|
814
|
+
mpz_init(rop->e);
|
|
815
|
+
mpz_init_set(rop->m, base->m);
|
|
816
|
+
int errcode = mpz_invert(rop->e, base->e, base->m);
|
|
817
|
+
if (errcode > 0) {
|
|
818
|
+
return (PyObject *) rop;
|
|
819
|
+
}
|
|
820
|
+
Py_DECREF(rop);
|
|
821
|
+
EXIT_IF(TRUE, "could not find a modular inverse");
|
|
822
|
+
}
|
|
823
|
+
}
|
|
824
|
+
EXIT_IF(TRUE, "not an integer object type.");
|
|
825
|
+
}
|
|
826
|
+
|
|
827
|
+
static PyObject *Integer_long(PyObject *o1) {
|
|
828
|
+
if (PyInteger_Check(o1)) {
|
|
829
|
+
Integer *value = (Integer *) o1;
|
|
830
|
+
if (mpz_sgn(value->m) != 0)
|
|
831
|
+
_reduce(value);
|
|
832
|
+
return mpzToLongObj(value->e);
|
|
833
|
+
}
|
|
834
|
+
|
|
835
|
+
EXIT_IF(TRUE, "invalid argument.");
|
|
836
|
+
}
|
|
837
|
+
|
|
838
|
+
static PyObject *Integer_reduce(PyObject *self, PyObject *args) {
|
|
839
|
+
if (PyInteger_Check(args)) {
|
|
840
|
+
Integer *in = (Integer *) args;
|
|
841
|
+
if(in->initialized) {
|
|
842
|
+
Integer *rop = createNewInteger();
|
|
843
|
+
mpz_init_set(rop->e, in->e);
|
|
844
|
+
mpz_init_set(rop->m, in->m);
|
|
845
|
+
if (mpz_sgn(rop->m) != 0)
|
|
846
|
+
_reduce(rop);
|
|
847
|
+
return (PyObject *) rop;
|
|
848
|
+
}
|
|
849
|
+
}
|
|
850
|
+
|
|
851
|
+
EXIT_IF(TRUE, "invalid argument.");
|
|
852
|
+
}
|
|
853
|
+
|
|
854
|
+
|
|
855
|
+
/** a / b mod N ...
|
|
856
|
+
* only defined when b is invertible modulo N, meaning a*b mod N = c*b mod N iff b has b^-1 s.t.
|
|
857
|
+
* b*b^-1 = 1 mod N.
|
|
858
|
+
*/
|
|
859
|
+
static PyObject *Integer_div(PyObject *o1, PyObject *o2) {
|
|
860
|
+
Integer *lhs = NULL, *rhs = NULL, *rop = NULL;
|
|
861
|
+
int foundLHS = FALSE, foundRHS = FALSE, errorOccured = FALSE;
|
|
862
|
+
mpz_t lhs_mpz, rhs_mpz;
|
|
863
|
+
mpz_init(lhs_mpz);
|
|
864
|
+
mpz_init(rhs_mpz);
|
|
865
|
+
|
|
866
|
+
Convert_Types(o1, o2, lhs, rhs, foundLHS, foundRHS, lhs_mpz, rhs_mpz, errorOccured);
|
|
867
|
+
// perform operation
|
|
868
|
+
if(errorOccured) {
|
|
869
|
+
mpz_clear(lhs_mpz);
|
|
870
|
+
mpz_clear(rhs_mpz);
|
|
871
|
+
ErrorMsg("invalid left or right operand type.");
|
|
872
|
+
}
|
|
873
|
+
else if (foundRHS && mpz_sgn(rhs_mpz) > 0) {
|
|
874
|
+
/* Let d = gcd(a, n). The congruence equation ax = b (mod n) has a solution x if and only if d divides b,
|
|
875
|
+
* in which case there are exactly d solutions between [0, n-1] these solutions are all congruent modulo n/d. */
|
|
876
|
+
rop = createNewInteger();
|
|
877
|
+
mpz_init_set(rop->e, lhs->e);
|
|
878
|
+
mpz_init_set(rop->m, lhs->m);
|
|
879
|
+
if (mpz_divisible_p(lhs->e, rhs_mpz) != 0) {
|
|
880
|
+
if (mpz_sgn(lhs->m) == 0) {
|
|
881
|
+
mpz_divexact(rop->e, lhs->e, rhs_mpz);
|
|
882
|
+
}
|
|
883
|
+
}
|
|
884
|
+
else if(mpz_sgn(rop->m) > 0 && mpz_cmp_ui(rhs_mpz, 1) == 0) {
|
|
885
|
+
mpz_mod(rop->e, rop->e, rop->m);
|
|
886
|
+
if(mpz_cmp(rop->e, rop->m) < 0) { // check if e < m, then divide e / rhs_value.
|
|
887
|
+
// EXIT_IF(TRUE, "unimplemented operation.");
|
|
888
|
+
// mpz_init_set_ui(tmp, lhs_value);
|
|
889
|
+
// mpz_gcd(tmp, tmp, rop->m);
|
|
890
|
+
// mpz_div(rop->e, tmp, rop->e);
|
|
891
|
+
// mpz_clear(tmp);
|
|
892
|
+
}
|
|
893
|
+
}
|
|
894
|
+
} else if (foundLHS && mpz_sgn(lhs_mpz) > 0) {
|
|
895
|
+
rop = createNewInteger();
|
|
896
|
+
mpz_init(rop->e);
|
|
897
|
+
int rhs_mod = mpz_sgn(rhs->m);
|
|
898
|
+
if(rhs_mod > 0) {
|
|
899
|
+
mpz_init_set(rop->m, rhs->m);
|
|
900
|
+
int errcode = mpz_invert(rop->e, rhs->e, rhs->m);
|
|
901
|
+
if(errcode == 0) {
|
|
902
|
+
Py_DECREF(rop);
|
|
903
|
+
mpz_clear(lhs_mpz);
|
|
904
|
+
mpz_clear(rhs_mpz);
|
|
905
|
+
ErrorMsg("division failed: could not find modular inverse.\n");
|
|
906
|
+
}
|
|
907
|
+
|
|
908
|
+
if(mpz_cmp_ui(lhs_mpz, 1) != 0) {
|
|
909
|
+
mpz_mul(rop->e, lhs_mpz, rop->e);
|
|
910
|
+
mpz_mod(rop->e, rop->e, rop->m);
|
|
911
|
+
}
|
|
912
|
+
}
|
|
913
|
+
else if(rhs_mod == 0 && mpz_divisible_p(lhs_mpz, rhs->e) != 0) {
|
|
914
|
+
rop = createNewInteger();
|
|
915
|
+
mpz_init(rop->e);
|
|
916
|
+
mpz_init_set(rop->m, rhs->m);
|
|
917
|
+
mpz_divexact(rop->e, lhs_mpz, rhs->e);
|
|
918
|
+
}
|
|
919
|
+
} else {
|
|
920
|
+
// printf("lhs and rhs init? => ");
|
|
921
|
+
if (mpz_cmp(lhs->m, rhs->m) == 0 && mpz_sgn(lhs->m) > 0) {
|
|
922
|
+
mpz_t rhs_inv;
|
|
923
|
+
mpz_init(rhs_inv);
|
|
924
|
+
mpz_invert(rhs_inv, rhs->e, rhs->m);
|
|
925
|
+
debug("rhs_inv...\n");
|
|
926
|
+
print_mpz(rhs_inv, 10);
|
|
927
|
+
|
|
928
|
+
rop = createNewInteger();
|
|
929
|
+
mpz_init(rop->e);
|
|
930
|
+
mpz_init_set(rop->m, lhs->m);
|
|
931
|
+
mpz_mul(rop->e, lhs->e, rhs_inv);
|
|
932
|
+
mpz_mod(rop->e, rop->e, rop->m);
|
|
933
|
+
mpz_clear(rhs_inv);
|
|
934
|
+
} else if (mpz_cmp(lhs->m, rhs->m) == 0 && mpz_sgn(lhs->m) == 0) {
|
|
935
|
+
rop = createNewInteger();
|
|
936
|
+
mpz_init(rop->e);
|
|
937
|
+
mpz_init_set(rop->m, lhs->m);
|
|
938
|
+
mpz_div(rop->e, lhs->e, rhs->e);
|
|
939
|
+
}
|
|
940
|
+
}
|
|
941
|
+
|
|
942
|
+
mpz_clear(lhs_mpz);
|
|
943
|
+
mpz_clear(rhs_mpz);
|
|
944
|
+
if (rop != NULL && mpz_sgn(rop->e) == 0) {
|
|
945
|
+
//PyObject_Del(rop);
|
|
946
|
+
Py_DECREF(rop);
|
|
947
|
+
EXIT_IF(TRUE, "division failed: could not find modular inverse.");
|
|
948
|
+
}
|
|
949
|
+
#ifdef BENCHMARK_ENABLED
|
|
950
|
+
UPDATE_BENCHMARK(DIVISION, tmpBench);
|
|
951
|
+
#endif
|
|
952
|
+
return (PyObject *) rop;
|
|
953
|
+
}
|
|
954
|
+
|
|
955
|
+
static PyObject *Integer_pow(PyObject *o1, PyObject *o2, PyObject *o3) {
|
|
956
|
+
Integer *lhs = NULL, *rhs = NULL, *rop = NULL;
|
|
957
|
+
int foundLHS = FALSE, foundRHS = FALSE;
|
|
958
|
+
mpz_t exponent;
|
|
959
|
+
mpz_init(exponent);
|
|
960
|
+
|
|
961
|
+
Convert_Types2(o1, o2, lhs, rhs, foundLHS, foundRHS);
|
|
962
|
+
// TODO: handle foundLHS (e.g. 2 ** <int.Elem>)
|
|
963
|
+
if (foundRHS) {
|
|
964
|
+
debug("foundRHS!\n");
|
|
965
|
+
// long rhs = PyLong_AsLong(o2);
|
|
966
|
+
longObjToMPZ(exponent, o2);
|
|
967
|
+
|
|
968
|
+
if(PyErr_Occurred() || mpz_sgn(exponent) >= 0) {
|
|
969
|
+
//PyErr_Print(); // for debug purposes
|
|
970
|
+
PyErr_Clear();
|
|
971
|
+
debug("exponent is positive\n");
|
|
972
|
+
int sgn = mpz_sgn(lhs->m);
|
|
973
|
+
if(sgn > 0) {
|
|
974
|
+
if(mpz_odd_p(lhs->m) > 0) {
|
|
975
|
+
// mpz_t exp;
|
|
976
|
+
// mpz_init(exp);
|
|
977
|
+
// longObjToMPZ(exp, o2);
|
|
978
|
+
// print_mpz(exp, 10);
|
|
979
|
+
rop = createNewInteger();
|
|
980
|
+
mpz_init(rop->e);
|
|
981
|
+
mpz_init_set(rop->m, lhs->m);
|
|
982
|
+
mpz_powm_sec(rop->e, lhs->e, exponent, rop->m);
|
|
983
|
+
}
|
|
984
|
+
}
|
|
985
|
+
else if(sgn == 0) { // no modulus
|
|
986
|
+
unsigned long int exp = PyLong_AsUnsignedLong(o2);
|
|
987
|
+
EXIT_IF(PyErr_Occurred(), "integer too large to exponentiate without modulus.");
|
|
988
|
+
rop = createNewInteger();
|
|
989
|
+
mpz_init(rop->e);
|
|
990
|
+
mpz_init_set(rop->m, lhs->m);
|
|
991
|
+
mpz_pow_ui(rop->e, lhs->e, exp);
|
|
992
|
+
}
|
|
993
|
+
else {
|
|
994
|
+
mpz_clear(exponent);
|
|
995
|
+
EXIT_IF(TRUE, "cannot exponentiate integers without modulus.");
|
|
996
|
+
}
|
|
997
|
+
}
|
|
998
|
+
else if(mpz_cmp_si(exponent, -1) == 0) {
|
|
999
|
+
debug("find modular inverse.\n");
|
|
1000
|
+
rop = createNewInteger();
|
|
1001
|
+
mpz_init(rop->e);
|
|
1002
|
+
mpz_init_set(rop->m, lhs->m);
|
|
1003
|
+
int errcode = mpz_invert(rop->e, lhs->e, lhs->m);
|
|
1004
|
+
if(errcode == 0) {
|
|
1005
|
+
Py_XDECREF(rop);
|
|
1006
|
+
mpz_clear(exponent);
|
|
1007
|
+
ErrorMsg("failed to find modular inverse.\n");
|
|
1008
|
+
}
|
|
1009
|
+
}
|
|
1010
|
+
else {
|
|
1011
|
+
// less than -1.
|
|
1012
|
+
rop = createNewInteger();
|
|
1013
|
+
mpz_init(rop->e);
|
|
1014
|
+
mpz_init_set(rop->m, lhs->m);
|
|
1015
|
+
int errcode = mpz_invert(rop->e, lhs->e, rop->m);
|
|
1016
|
+
if(errcode > 0) {
|
|
1017
|
+
mpz_neg(exponent, exponent);
|
|
1018
|
+
mpz_powm_sec(rop->e, rop->e, exponent, rop->m);
|
|
1019
|
+
}
|
|
1020
|
+
else {
|
|
1021
|
+
mpz_clear(exponent);
|
|
1022
|
+
Py_XDECREF(rop);
|
|
1023
|
+
ErrorMsg("failed to find modular inverse.\n");
|
|
1024
|
+
}
|
|
1025
|
+
}
|
|
1026
|
+
mpz_clear(exponent);
|
|
1027
|
+
} else if (foundLHS) {
|
|
1028
|
+
mpz_clear(exponent);
|
|
1029
|
+
ErrorMsg("unsupported operation: left operand expected to be a charm.integer type.");
|
|
1030
|
+
} else {
|
|
1031
|
+
// if rhs has negative exponent
|
|
1032
|
+
if (mpz_sgn(rhs->e) < 0) {
|
|
1033
|
+
if(mpz_sgn(lhs->m) > 0) {
|
|
1034
|
+
// base modulus is positive
|
|
1035
|
+
rop = createNewInteger();
|
|
1036
|
+
mpz_init(rop->e);
|
|
1037
|
+
mpz_init_set(rop->m, lhs->m);
|
|
1038
|
+
int errcode = mpz_invert(rop->e, lhs->e, rop->m);
|
|
1039
|
+
if(errcode > 0) {
|
|
1040
|
+
mpz_t exp;
|
|
1041
|
+
mpz_init_set(exp, rhs->e);
|
|
1042
|
+
mpz_neg(exp, exp);
|
|
1043
|
+
mpz_powm_sec(rop->e, rop->e, exp, rop->m);
|
|
1044
|
+
mpz_clear(exp);
|
|
1045
|
+
goto leave;
|
|
1046
|
+
}
|
|
1047
|
+
else {
|
|
1048
|
+
mpz_clear(exponent);
|
|
1049
|
+
Py_XDECREF(rop);
|
|
1050
|
+
ErrorMsg("failed to find modular inverse.\n");
|
|
1051
|
+
}
|
|
1052
|
+
}
|
|
1053
|
+
}
|
|
1054
|
+
|
|
1055
|
+
// result takes modulus of base
|
|
1056
|
+
debug("both integer objects: ");
|
|
1057
|
+
if (mpz_sgn(lhs->m) > 0) {
|
|
1058
|
+
// common case for modular exponentiation
|
|
1059
|
+
rop = createNewInteger();
|
|
1060
|
+
mpz_init(rop->e);
|
|
1061
|
+
mpz_init_set(rop->m, lhs->m);
|
|
1062
|
+
mpz_powm_sec(rop->e, lhs->e, rhs->e, rop->m);
|
|
1063
|
+
}
|
|
1064
|
+
// lhs is a reg int
|
|
1065
|
+
else if (mpz_fits_ulong_p(lhs->e) && mpz_fits_ulong_p(rhs->e)) {
|
|
1066
|
+
// convert base (lhs) to an unsigned long (if possible)
|
|
1067
|
+
unsigned long int base = mpz_get_ui(lhs->e);
|
|
1068
|
+
unsigned long int exp = mpz_get_ui(rhs->e);
|
|
1069
|
+
rop = createNewInteger();
|
|
1070
|
+
mpz_init(rop->e);
|
|
1071
|
+
mpz_init(rop->m);
|
|
1072
|
+
mpz_ui_pow_ui(rop->e, base, exp);
|
|
1073
|
+
}
|
|
1074
|
+
// lhs reg int and rhs can be represented as ulong
|
|
1075
|
+
else if (mpz_fits_ulong_p(rhs->e)) {
|
|
1076
|
+
unsigned long int exp = mpz_get_ui(rhs->e);
|
|
1077
|
+
rop = createNewInteger();
|
|
1078
|
+
mpz_init(rop->e);
|
|
1079
|
+
mpz_init(rop->m);
|
|
1080
|
+
mpz_pow_ui(rop->e, lhs->e, exp);
|
|
1081
|
+
} else { // last option...
|
|
1082
|
+
// cannot represent reg ints as ulong's, so error out.
|
|
1083
|
+
EXIT_IF(TRUE, "could not exponentiate integers.");
|
|
1084
|
+
}
|
|
1085
|
+
}
|
|
1086
|
+
|
|
1087
|
+
leave:
|
|
1088
|
+
#ifdef BENCHMARK_ENABLED
|
|
1089
|
+
UPDATE_BENCHMARK(EXPONENTIATION, tmpBench);
|
|
1090
|
+
#endif
|
|
1091
|
+
return (PyObject *) rop;
|
|
1092
|
+
}
|
|
1093
|
+
|
|
1094
|
+
/*
|
|
1095
|
+
* Description: hash elements into a group element
|
|
1096
|
+
* inputs: group elements, p, q, and True or False
|
|
1097
|
+
* (return value mod p when TRUE and value mod q when FALSE)
|
|
1098
|
+
*/
|
|
1099
|
+
static PyObject *Integer_hash(PyObject *self, PyObject *args) {
|
|
1100
|
+
PyObject *object, *order, *order2;
|
|
1101
|
+
Integer *pObj, *qObj;
|
|
1102
|
+
uint8_t *rop_buf = NULL;
|
|
1103
|
+
mpz_t p, q, v, tmp;
|
|
1104
|
+
mpz_init(p);
|
|
1105
|
+
mpz_init(q);
|
|
1106
|
+
mpz_init(v);
|
|
1107
|
+
mpz_init(tmp);
|
|
1108
|
+
int modP = FALSE;
|
|
1109
|
+
|
|
1110
|
+
if (PyArg_ParseTuple(args, "OOO|i", &object, &order, &order2, &modP)) {
|
|
1111
|
+
// one single integer group element
|
|
1112
|
+
if (PyInteger_Check(order) && PyInteger_Check(order2)) {
|
|
1113
|
+
pObj = (Integer *) order;
|
|
1114
|
+
qObj = (Integer *) order2;
|
|
1115
|
+
mpz_set(p, pObj->e);
|
|
1116
|
+
mpz_set(q, qObj->e);
|
|
1117
|
+
mpz_mul_ui(tmp, q, 2);
|
|
1118
|
+
mpz_add_ui(tmp, tmp, 1);
|
|
1119
|
+
|
|
1120
|
+
if (mpz_cmp(tmp, p) != 0) {
|
|
1121
|
+
PyErr_SetString(IntegerError,
|
|
1122
|
+
"can only encode messages into groups where p = 2*q+1.");
|
|
1123
|
+
goto cleanup;
|
|
1124
|
+
}
|
|
1125
|
+
} else {
|
|
1126
|
+
PyErr_SetString(IntegerError,
|
|
1127
|
+
"failed to specify large primes p and q.");
|
|
1128
|
+
goto cleanup;
|
|
1129
|
+
}
|
|
1130
|
+
|
|
1131
|
+
int i, object_size = PySequence_Length(object);
|
|
1132
|
+
|
|
1133
|
+
// dealing with a tuple element here...
|
|
1134
|
+
if (object_size > 0) {
|
|
1135
|
+
|
|
1136
|
+
int o_size = 0;
|
|
1137
|
+
// get length of all objects
|
|
1138
|
+
for (i = 0; i < object_size; i++) {
|
|
1139
|
+
PyObject *tmpObject = PySequence_GetItem(object, i);
|
|
1140
|
+
if (PyInteger_Check(tmpObject)) {
|
|
1141
|
+
Integer *object1 = (Integer *) tmpObject;
|
|
1142
|
+
if (object1->initialized) {
|
|
1143
|
+
o_size += size(object1->e);
|
|
1144
|
+
}
|
|
1145
|
+
}
|
|
1146
|
+
Py_XDECREF(tmpObject);
|
|
1147
|
+
}
|
|
1148
|
+
|
|
1149
|
+
/* allocate space big enough to hold exported objects */
|
|
1150
|
+
rop_buf = (uint8_t *) malloc(o_size + 1);
|
|
1151
|
+
if (rop_buf == NULL) return NULL;
|
|
1152
|
+
memset(rop_buf, 0, o_size);
|
|
1153
|
+
int cur_ptr = 0;
|
|
1154
|
+
/* export objects here using mpz_export into allocated buffer */
|
|
1155
|
+
for (i = 0; i < object_size; i++) {
|
|
1156
|
+
PyObject *tmpObject = PySequence_GetItem(object, i);
|
|
1157
|
+
|
|
1158
|
+
if (PyInteger_Check(tmpObject)) {
|
|
1159
|
+
Integer *tmpObject2 = (Integer *) tmpObject;
|
|
1160
|
+
if (tmpObject2->initialized) {
|
|
1161
|
+
uint8_t *target_ptr = (uint8_t *) (rop_buf + cur_ptr);
|
|
1162
|
+
size_t len = 0;
|
|
1163
|
+
mpz_export(target_ptr, &len, 1, sizeof(char), 0, 0,
|
|
1164
|
+
tmpObject2->e);
|
|
1165
|
+
cur_ptr += size(tmpObject2->e);
|
|
1166
|
+
}
|
|
1167
|
+
}
|
|
1168
|
+
Py_XDECREF(tmpObject);
|
|
1169
|
+
}
|
|
1170
|
+
|
|
1171
|
+
// hash the buffer
|
|
1172
|
+
uint8_t hash_buf2[HASH_LEN + 1];
|
|
1173
|
+
hash_to_bytes(rop_buf, o_size, hash_buf2, HASH_LEN,
|
|
1174
|
+
HASH_FUNCTION_KEM_DERIVE);
|
|
1175
|
+
free(rop_buf);
|
|
1176
|
+
|
|
1177
|
+
// mpz_import hash to a element from 1 to q-1 inclusive.
|
|
1178
|
+
mpz_import(tmp, HASH_LEN, 1, sizeof(hash_buf2[0]), 0, 0, hash_buf2);
|
|
1179
|
+
// now hash to match desired output size of q.
|
|
1180
|
+
if (modP)
|
|
1181
|
+
mpz_mod(tmp, tmp, p);
|
|
1182
|
+
else
|
|
1183
|
+
mpz_mod(tmp, tmp, q);
|
|
1184
|
+
debug("print group tuple...\n");
|
|
1185
|
+
print_mpz(tmp, 2);
|
|
1186
|
+
|
|
1187
|
+
// calculate ceiling |q|/160 => blocks
|
|
1188
|
+
int i, blocks = ceil((double) size(q) / (HASH_LEN * 8));
|
|
1189
|
+
debug("blocks => '%d'\n", blocks);
|
|
1190
|
+
size_t out_len = HASH_LEN * blocks;
|
|
1191
|
+
uint8_t out_buf[(out_len * 2) + 1];
|
|
1192
|
+
memset(out_buf, 0, out_len*2);
|
|
1193
|
+
|
|
1194
|
+
if (blocks > 1) {
|
|
1195
|
+
for (i = 1; i <= blocks; i++) {
|
|
1196
|
+
// how to add num in front of tmp_buf?
|
|
1197
|
+
// compute sha1( i || tmp_buf ) ->
|
|
1198
|
+
uint8_t *ptr = (uint8_t *) &out_buf[HASH_LEN * i];
|
|
1199
|
+
debug("pointer to block => '%p\n", ptr);
|
|
1200
|
+
// doesn't work like this yet
|
|
1201
|
+
hash_to_group_element(tmp, i, ptr);
|
|
1202
|
+
}
|
|
1203
|
+
} else {
|
|
1204
|
+
debug("Only 1 block to hash.\n");
|
|
1205
|
+
hash_to_group_element(tmp, -1, out_buf);
|
|
1206
|
+
}
|
|
1207
|
+
|
|
1208
|
+
debug("print out_len => '%zd'\n", out_len);
|
|
1209
|
+
debug("print out_buf...\n");
|
|
1210
|
+
printf_buffer_as_hex(out_buf, out_len);
|
|
1211
|
+
// convert v' to mpz_t type mod q => v
|
|
1212
|
+
mpz_import(v, out_len, 1, sizeof(char), 0, 0, out_buf);
|
|
1213
|
+
mpz_t modulus;
|
|
1214
|
+
if (modP) {
|
|
1215
|
+
// v = v' mod p
|
|
1216
|
+
debug("doing mod p\n");
|
|
1217
|
+
mpz_mod(v, v, p);
|
|
1218
|
+
// y = v^2 mod q
|
|
1219
|
+
mpz_powm_ui(v, v, 2, q);
|
|
1220
|
+
mpz_init_set(modulus, q);
|
|
1221
|
+
} else {
|
|
1222
|
+
debug("doing mod q\n");
|
|
1223
|
+
mpz_mod(v, v, q);
|
|
1224
|
+
// y = v^2 mod p : return y mod p
|
|
1225
|
+
mpz_powm_ui(v, v, 2, p);
|
|
1226
|
+
mpz_init_set(modulus, p);
|
|
1227
|
+
}
|
|
1228
|
+
debug("print v => \n");
|
|
1229
|
+
print_mpz(v, 10);
|
|
1230
|
+
Integer *rop = createNewInteger();
|
|
1231
|
+
mpz_init_set(rop->e, v);
|
|
1232
|
+
mpz_init_set(rop->m, modulus);
|
|
1233
|
+
mpz_clear(p);
|
|
1234
|
+
mpz_clear(q);
|
|
1235
|
+
mpz_clear(v);
|
|
1236
|
+
mpz_clear(tmp);
|
|
1237
|
+
mpz_clear(modulus);
|
|
1238
|
+
return (PyObject *) rop;
|
|
1239
|
+
} else { /* non-tuple element - maybe single element? */
|
|
1240
|
+
Integer *obj = (Integer *) object;
|
|
1241
|
+
|
|
1242
|
+
// make sure object was initialized
|
|
1243
|
+
if (!obj->initialized) {
|
|
1244
|
+
PyErr_SetString(IntegerError, "integer object not initialized.");
|
|
1245
|
+
goto cleanup;
|
|
1246
|
+
}
|
|
1247
|
+
// not a group element
|
|
1248
|
+
if (mpz_cmp(p, obj->m) != 0) {
|
|
1249
|
+
PyErr_SetString(IntegerError,
|
|
1250
|
+
"integer object not a group element.");
|
|
1251
|
+
goto cleanup;
|
|
1252
|
+
}
|
|
1253
|
+
|
|
1254
|
+
// mpz_export base to a string (ignore modulus) => val
|
|
1255
|
+
size_t count = 0;
|
|
1256
|
+
rop_buf = (uint8_t *) mpz_export(NULL, &count, 1, sizeof(char), 0,
|
|
1257
|
+
0, obj->e);
|
|
1258
|
+
|
|
1259
|
+
// hash the buffer
|
|
1260
|
+
uint8_t hash_buf[HASH_LEN + 1];
|
|
1261
|
+
hash_to_bytes(rop_buf, (int) count, hash_buf, HASH_LEN,
|
|
1262
|
+
HASH_FUNCTION_KEM_DERIVE);
|
|
1263
|
+
|
|
1264
|
+
// mpz_import hash to a element from 1 to q-1 inclusive.
|
|
1265
|
+
mpz_import(tmp, HASH_LEN, 1, sizeof(hash_buf[0]), 0, 0, hash_buf);
|
|
1266
|
+
// now hash to match desired output size of q.
|
|
1267
|
+
if (modP)
|
|
1268
|
+
mpz_mod(tmp, tmp, p);
|
|
1269
|
+
else
|
|
1270
|
+
mpz_mod(tmp, tmp, q);
|
|
1271
|
+
print_mpz(tmp, 2);
|
|
1272
|
+
|
|
1273
|
+
// calculate ceiling |q|/160 => blocks
|
|
1274
|
+
int i, blocks = ceil((double) size(q) / (HASH_LEN * 8));
|
|
1275
|
+
debug("blocks => '%d'\n", blocks);
|
|
1276
|
+
size_t out_len = HASH_LEN * blocks;
|
|
1277
|
+
uint8_t out_buf[out_len + 4];
|
|
1278
|
+
memset(out_buf, 0, out_len);
|
|
1279
|
+
|
|
1280
|
+
for (i = 0; i < blocks; i++) {
|
|
1281
|
+
// how to add num in front of tmp_buf?
|
|
1282
|
+
// compute sha1( i || tmp_buf ) ->
|
|
1283
|
+
uint8_t *ptr = (uint8_t *) &out_buf[HASH_LEN * i];
|
|
1284
|
+
debug("pointer to block => '%p\n", ptr);
|
|
1285
|
+
// doesn't work like this yet
|
|
1286
|
+
hash_to_group_element(tmp, i, ptr);
|
|
1287
|
+
}
|
|
1288
|
+
|
|
1289
|
+
// convert v' to mpz_t type mod q => v
|
|
1290
|
+
mpz_import(v, out_len, 1, sizeof(out_buf[0]), 0, 0, out_buf);
|
|
1291
|
+
mpz_t modulus;
|
|
1292
|
+
if (modP) {
|
|
1293
|
+
// v = v' mod p
|
|
1294
|
+
debug("doing mod p");
|
|
1295
|
+
mpz_mod(v, v, p);
|
|
1296
|
+
// y = v^2 mod q
|
|
1297
|
+
mpz_powm_ui(v, v, 2, q);
|
|
1298
|
+
mpz_init_set(modulus, q);
|
|
1299
|
+
} else {
|
|
1300
|
+
debug("doing mod q");
|
|
1301
|
+
mpz_mod(v, v, q);
|
|
1302
|
+
// y = v^2 mod p : return y mod p
|
|
1303
|
+
mpz_powm_ui(v, v, 2, p);
|
|
1304
|
+
mpz_init_set(modulus, p);
|
|
1305
|
+
}
|
|
1306
|
+
|
|
1307
|
+
free(rop_buf);
|
|
1308
|
+
print_mpz(v, 10);
|
|
1309
|
+
Integer *rop = createNewInteger();
|
|
1310
|
+
mpz_init_set(rop->e, v);
|
|
1311
|
+
mpz_init_set(rop->e, modulus);
|
|
1312
|
+
mpz_clear(v);
|
|
1313
|
+
mpz_clear(p);
|
|
1314
|
+
mpz_clear(q);
|
|
1315
|
+
mpz_clear(tmp);
|
|
1316
|
+
mpz_clear(modulus);
|
|
1317
|
+
return (PyObject *) rop;
|
|
1318
|
+
}
|
|
1319
|
+
// a tuple of various elements
|
|
1320
|
+
|
|
1321
|
+
}
|
|
1322
|
+
|
|
1323
|
+
cleanup:
|
|
1324
|
+
mpz_clear(v);
|
|
1325
|
+
mpz_clear(p);
|
|
1326
|
+
mpz_clear(q);
|
|
1327
|
+
mpz_clear(tmp);
|
|
1328
|
+
return NULL;
|
|
1329
|
+
|
|
1330
|
+
}
|
|
1331
|
+
|
|
1332
|
+
//static PyObject *Integer_reduce(Integer *self, PyObject *arg) {
|
|
1333
|
+
//
|
|
1334
|
+
// if (!self->initialized) {
|
|
1335
|
+
// PyErr_SetString(IntegerError, "invalid integer object.");
|
|
1336
|
+
// Py_INCREF(Py_False);
|
|
1337
|
+
// return Py_False;
|
|
1338
|
+
// }
|
|
1339
|
+
//
|
|
1340
|
+
// _reduce(self);
|
|
1341
|
+
// Py_INCREF(Py_True);
|
|
1342
|
+
// return Py_True;
|
|
1343
|
+
//}
|
|
1344
|
+
|
|
1345
|
+
static PyObject *Integer_remainder(PyObject *o1, PyObject *o2) {
|
|
1346
|
+
|
|
1347
|
+
Integer *lhs = NULL, *rhs = NULL, *rop = NULL;
|
|
1348
|
+
int foundLHS = FALSE, foundRHS = FALSE;
|
|
1349
|
+
|
|
1350
|
+
Convert_Types2(o1, o2, lhs, rhs, foundLHS, foundRHS);
|
|
1351
|
+
|
|
1352
|
+
if (foundLHS) {
|
|
1353
|
+
rop = createNewInteger();
|
|
1354
|
+
mpz_init(rop->e);
|
|
1355
|
+
mpz_init_set(rop->m, rhs->m);
|
|
1356
|
+
if (_PyLong_Check(o1)) {
|
|
1357
|
+
PyObject *tmp = PyNumber_Long(o1);
|
|
1358
|
+
mpz_t e;
|
|
1359
|
+
mpz_init(e);
|
|
1360
|
+
longObjToMPZ(e, tmp);
|
|
1361
|
+
mpz_mod(rop->e, e, rhs->e);
|
|
1362
|
+
mpz_set(rop->m, rhs->e);
|
|
1363
|
+
mpz_clear(e);
|
|
1364
|
+
Py_XDECREF(tmp);
|
|
1365
|
+
} else if (PyInteger_Check(o1)) {
|
|
1366
|
+
Integer *tmp_mod = (Integer *) o1;
|
|
1367
|
+
// ignore the modulus of tmp_mod
|
|
1368
|
+
mpz_mod(rop->e, rhs->e, tmp_mod->e);
|
|
1369
|
+
mpz_set(rop->m, tmp_mod->e);
|
|
1370
|
+
}
|
|
1371
|
+
} else if (foundRHS) {
|
|
1372
|
+
rop = createNewInteger();
|
|
1373
|
+
mpz_init(rop->e);
|
|
1374
|
+
mpz_init_set(rop->m, lhs->m);
|
|
1375
|
+
if (_PyLong_Check(o2)) {
|
|
1376
|
+
PyObject *tmp = PyNumber_Long(o2);
|
|
1377
|
+
mpz_t modulus;
|
|
1378
|
+
mpz_init(modulus);
|
|
1379
|
+
longObjToMPZ(modulus, tmp);
|
|
1380
|
+
mpz_mod(rop->e, lhs->e, modulus);
|
|
1381
|
+
mpz_set(rop->m, modulus);
|
|
1382
|
+
mpz_clear(modulus);
|
|
1383
|
+
Py_XDECREF(tmp);
|
|
1384
|
+
}
|
|
1385
|
+
} else {
|
|
1386
|
+
rop = createNewInteger();
|
|
1387
|
+
mpz_init(rop->e);
|
|
1388
|
+
mpz_init_set(rop->m, rhs->e);
|
|
1389
|
+
mpz_mod(rop->e, lhs->e, rop->m);
|
|
1390
|
+
}
|
|
1391
|
+
return (PyObject *) rop;
|
|
1392
|
+
}
|
|
1393
|
+
|
|
1394
|
+
/* END: module function definitions */
|
|
1395
|
+
|
|
1396
|
+
/* START: helper function definition */
|
|
1397
|
+
//#define MAX_RABIN_MILLER_ROUNDS 255
|
|
1398
|
+
|
|
1399
|
+
static PyObject *testPrimality(PyObject *self, PyObject *arg) {
|
|
1400
|
+
int result = -1;
|
|
1401
|
+
|
|
1402
|
+
if (arg != NULL) {
|
|
1403
|
+
if (_PyLong_Check(arg)) {
|
|
1404
|
+
PyObject *obj = PyNumber_Long(arg);
|
|
1405
|
+
mpz_t value;
|
|
1406
|
+
mpz_init(value);
|
|
1407
|
+
longObjToMPZ(value, obj);
|
|
1408
|
+
result = mpz_probab_prime_p(value, MAX_RUN);
|
|
1409
|
+
mpz_clear(value);
|
|
1410
|
+
Py_XDECREF(obj);
|
|
1411
|
+
} else if (PyInteger_Check(arg)) {
|
|
1412
|
+
Integer *obj = (Integer *) arg;
|
|
1413
|
+
if (obj->initialized)
|
|
1414
|
+
result = mpz_probab_prime_p(obj->e, MAX_RUN);
|
|
1415
|
+
}
|
|
1416
|
+
}
|
|
1417
|
+
|
|
1418
|
+
if (result > 0) {
|
|
1419
|
+
debug("probably prime: %d\n", result);
|
|
1420
|
+
Py_INCREF(Py_True);
|
|
1421
|
+
return Py_True;
|
|
1422
|
+
} else if (result == 0) {
|
|
1423
|
+
debug("not prime.\n");
|
|
1424
|
+
Py_INCREF(Py_False);
|
|
1425
|
+
return Py_False;
|
|
1426
|
+
} else {
|
|
1427
|
+
PyErr_SetString(IntegerError, "invalid input.");
|
|
1428
|
+
return NULL;
|
|
1429
|
+
}
|
|
1430
|
+
}
|
|
1431
|
+
|
|
1432
|
+
static PyObject *genRandomBits(PyObject *self, PyObject *args) {
|
|
1433
|
+
unsigned int bits;
|
|
1434
|
+
|
|
1435
|
+
if (PyArg_ParseTuple(args, "i", &bits)) {
|
|
1436
|
+
if (bits > 0) {
|
|
1437
|
+
// generate random number that is in 0 to 2^n-1 range.
|
|
1438
|
+
// TODO: fix code very very soon!
|
|
1439
|
+
PyLongObject *v;
|
|
1440
|
+
unsigned char buff[sizeof(long)];
|
|
1441
|
+
long t;
|
|
1442
|
+
int ndigits = (bits + PyLong_SHIFT - 1) / PyLong_SHIFT;
|
|
1443
|
+
int digitsleft = ndigits;
|
|
1444
|
+
int bitsleft = bits;
|
|
1445
|
+
|
|
1446
|
+
v = _PyLong_New(ndigits);
|
|
1447
|
+
if (v != NULL) {
|
|
1448
|
+
digit *p = PythonLongVal(v);
|
|
1449
|
+
while (digitsleft > 1) {
|
|
1450
|
+
RAND_bytes(buff, sizeof(long));
|
|
1451
|
+
memcpy(&t, buff, sizeof(long));
|
|
1452
|
+
*p++ = (digit)(t & PyLong_MASK);
|
|
1453
|
+
digitsleft--;
|
|
1454
|
+
bitsleft -= PyLong_SHIFT;
|
|
1455
|
+
}
|
|
1456
|
+
|
|
1457
|
+
if (digitsleft == 1) {
|
|
1458
|
+
RAND_bytes(buff, sizeof(long));
|
|
1459
|
+
memcpy(&t, buff, sizeof(long));
|
|
1460
|
+
unsigned long mask = (1 << bitsleft) - 1;
|
|
1461
|
+
*p++ = (digit)(t & PyLong_MASK & mask);
|
|
1462
|
+
}
|
|
1463
|
+
|
|
1464
|
+
}
|
|
1465
|
+
return (PyObject *) v;
|
|
1466
|
+
}
|
|
1467
|
+
}
|
|
1468
|
+
|
|
1469
|
+
EXIT_IF(TRUE, "number of bits must be > 0.");
|
|
1470
|
+
}
|
|
1471
|
+
|
|
1472
|
+
static PyObject *genRandom(PyObject *self, PyObject *args) {
|
|
1473
|
+
PyObject *obj = NULL;
|
|
1474
|
+
Integer *rop = NULL;
|
|
1475
|
+
mpz_t N;
|
|
1476
|
+
|
|
1477
|
+
if (PyArg_ParseTuple(args, "O", &obj)) {
|
|
1478
|
+
|
|
1479
|
+
if (_PyLong_Check(obj)) {
|
|
1480
|
+
mpz_init(N);
|
|
1481
|
+
longObjToMPZ(N, obj);
|
|
1482
|
+
} else if (PyInteger_Check(obj)) {
|
|
1483
|
+
Integer *obj1 = (Integer *) obj;
|
|
1484
|
+
mpz_init_set(N, obj1->e);
|
|
1485
|
+
} else {
|
|
1486
|
+
/* error */
|
|
1487
|
+
EXIT_IF(TRUE, "invalid object type.");
|
|
1488
|
+
}
|
|
1489
|
+
|
|
1490
|
+
BIGNUM *s = BN_new(), *bN = BN_new();
|
|
1491
|
+
BN_one(s);
|
|
1492
|
+
mpzToBN(N, bN);
|
|
1493
|
+
rop = createNewInteger();
|
|
1494
|
+
mpz_init(rop->e);
|
|
1495
|
+
mpz_init_set(rop->m, N);
|
|
1496
|
+
|
|
1497
|
+
BN_rand_range(s, bN);
|
|
1498
|
+
bnToMPZ(s, rop->e);
|
|
1499
|
+
print_bn_dec(s);
|
|
1500
|
+
BN_free(s);
|
|
1501
|
+
BN_free(bN);
|
|
1502
|
+
mpz_clear(N);
|
|
1503
|
+
return (PyObject *) rop;
|
|
1504
|
+
}
|
|
1505
|
+
EXIT_IF(TRUE, "invalid arguments.");
|
|
1506
|
+
}
|
|
1507
|
+
|
|
1508
|
+
/* takes as input the number of bits and produces a prime number of that size. */
|
|
1509
|
+
static PyObject *genRandomPrime(PyObject *self, PyObject *args) {
|
|
1510
|
+
int bits, safe = FALSE;
|
|
1511
|
+
|
|
1512
|
+
if (PyArg_ParseTuple(args, "i|i", &bits, &safe)) {
|
|
1513
|
+
if (bits > 0) {
|
|
1514
|
+
// mpz_t tmp;
|
|
1515
|
+
Integer *rop = createNewInteger();
|
|
1516
|
+
mpz_init(rop->e);
|
|
1517
|
+
mpz_init(rop->m);
|
|
1518
|
+
|
|
1519
|
+
BIGNUM *bn = BN_new();
|
|
1520
|
+
/* This routine generates safe prime only when safe=TRUE in which prime, p is selected
|
|
1521
|
+
* iff (p-1)/2 is also prime.
|
|
1522
|
+
*
|
|
1523
|
+
* Use BN_generate_prime_ex() instead of deprecated BN_generate_prime().
|
|
1524
|
+
* This fixes Python 3.12+ hanging issues with prime generation.
|
|
1525
|
+
*/
|
|
1526
|
+
int result;
|
|
1527
|
+
if(safe == TRUE) // safe is non-zero
|
|
1528
|
+
result = BN_generate_prime_ex(bn, bits, safe, NULL, NULL, NULL);
|
|
1529
|
+
else
|
|
1530
|
+
/* generate strong primes only */
|
|
1531
|
+
result = BN_generate_prime_ex(bn, bits, FALSE, NULL, NULL, NULL);
|
|
1532
|
+
|
|
1533
|
+
if (!result) {
|
|
1534
|
+
BN_free(bn);
|
|
1535
|
+
mpz_clear(rop->e);
|
|
1536
|
+
mpz_clear(rop->m);
|
|
1537
|
+
PyMem_Free(rop);
|
|
1538
|
+
EXIT_IF(TRUE, "BN_generate_prime_ex failed");
|
|
1539
|
+
}
|
|
1540
|
+
|
|
1541
|
+
debug("Safe prime => ");
|
|
1542
|
+
print_bn_dec(bn);
|
|
1543
|
+
bnToMPZ(bn, rop->e);
|
|
1544
|
+
BN_free(bn);
|
|
1545
|
+
return (PyObject *) rop;
|
|
1546
|
+
}
|
|
1547
|
+
}
|
|
1548
|
+
|
|
1549
|
+
EXIT_IF(TRUE, "invalid input.");
|
|
1550
|
+
}
|
|
1551
|
+
|
|
1552
|
+
static PyObject *encode_message(PyObject *self, PyObject *args) {
|
|
1553
|
+
//char *m; // handle arbitrary messages
|
|
1554
|
+
uint8_t *old_m;
|
|
1555
|
+
int m_size;
|
|
1556
|
+
PyObject *order, *order2, *old_msg;
|
|
1557
|
+
Integer *pObj, *qObj;
|
|
1558
|
+
mpz_t p, q, result;
|
|
1559
|
+
mpz_t tmp, exp, rop;
|
|
1560
|
+
Integer *rop2;
|
|
1561
|
+
|
|
1562
|
+
if (PyArg_ParseTuple(args, "OOO", &old_msg, &order, &order2)) {
|
|
1563
|
+
// make sure p = 2 * q + 1
|
|
1564
|
+
if (PyInteger_Check(order) && PyInteger_Check(order2)) {
|
|
1565
|
+
mpz_init(p);
|
|
1566
|
+
mpz_init(q);
|
|
1567
|
+
mpz_init(result);
|
|
1568
|
+
|
|
1569
|
+
pObj = (Integer *) order;
|
|
1570
|
+
qObj = (Integer *) order2;
|
|
1571
|
+
mpz_set(p, pObj->e);
|
|
1572
|
+
mpz_set(q, qObj->e);
|
|
1573
|
+
mpz_mul_ui(result, q, 2);
|
|
1574
|
+
mpz_add_ui(result, result, 1);
|
|
1575
|
+
|
|
1576
|
+
if (mpz_cmp(result, p) != 0) {
|
|
1577
|
+
mpz_clear(p);
|
|
1578
|
+
mpz_clear(q);
|
|
1579
|
+
mpz_clear(result);
|
|
1580
|
+
EXIT_IF(TRUE, "can only encode messages into groups where p = 2*q+1.");
|
|
1581
|
+
}
|
|
1582
|
+
} else {
|
|
1583
|
+
EXIT_IF(TRUE, "failed to specify large primes p and q.");
|
|
1584
|
+
}
|
|
1585
|
+
mpz_clear(q);
|
|
1586
|
+
mpz_clear(result);
|
|
1587
|
+
|
|
1588
|
+
// for python 3
|
|
1589
|
+
if(PyBytes_Check(old_msg)) {
|
|
1590
|
+
old_m = (uint8_t *) PyBytes_AS_STRING(old_msg);
|
|
1591
|
+
m_size = strlen((char *) old_m);
|
|
1592
|
+
debug("Message => ");
|
|
1593
|
+
printf_buffer_as_hex(old_m, m_size);
|
|
1594
|
+
debug("Size => '%d'\n", m_size);
|
|
1595
|
+
|
|
1596
|
+
if(m_size > MSG_LEN-2) {
|
|
1597
|
+
mpz_clear(p);
|
|
1598
|
+
EXIT_IF(TRUE, "message too large. Cannot represent as an element of Zp.");
|
|
1599
|
+
}
|
|
1600
|
+
}
|
|
1601
|
+
else {
|
|
1602
|
+
mpz_clear(p);
|
|
1603
|
+
EXIT_IF(TRUE, "message not a bytes object");
|
|
1604
|
+
}
|
|
1605
|
+
|
|
1606
|
+
//longest message can be is 128 characters (1024 bits) => check on this!!!
|
|
1607
|
+
char m[MSG_LEN+2]; //128 byte message, 1 byte length, null byte
|
|
1608
|
+
m[0] = m_size & 0xFF; //->this one works too...results in order 207
|
|
1609
|
+
snprintf((m+1), MSG_LEN+1, "%s", old_m); //copying message over
|
|
1610
|
+
m_size = m_size + 1; //we added an extra byte
|
|
1611
|
+
|
|
1612
|
+
// p and q values valid
|
|
1613
|
+
mpz_init(tmp);
|
|
1614
|
+
mpz_import(tmp, m_size, 1, sizeof(m[0]), 0, 0, m);
|
|
1615
|
+
// bytes_to_mpz(tmp2, (const unsigned char *) m, (size_t) m_size);
|
|
1616
|
+
|
|
1617
|
+
// perform encoding...
|
|
1618
|
+
// get the order object (only works for p = 2q + 1)
|
|
1619
|
+
mpz_init(exp);
|
|
1620
|
+
mpz_init(rop);
|
|
1621
|
+
mpz_add_ui(tmp, tmp, 1);
|
|
1622
|
+
|
|
1623
|
+
// (p - 1) / 2
|
|
1624
|
+
mpz_sub_ui(exp, p, 1);
|
|
1625
|
+
mpz_divexact_ui(exp, exp, 2);
|
|
1626
|
+
// y ^ exp mod p
|
|
1627
|
+
mpz_powm(rop, tmp, exp, p);
|
|
1628
|
+
|
|
1629
|
+
// check if rop is 1
|
|
1630
|
+
if (mpz_cmp_ui(rop, 1) == 0) {
|
|
1631
|
+
// if so, then we can return y
|
|
1632
|
+
debug("true case: just return y.\n");
|
|
1633
|
+
print_mpz(p, 10);
|
|
1634
|
+
print_mpz(tmp, 10);
|
|
1635
|
+
|
|
1636
|
+
rop2 = createNewInteger();
|
|
1637
|
+
mpz_init(rop2->e);
|
|
1638
|
+
mpz_init_set(rop2->m, p);
|
|
1639
|
+
mpz_set(rop2->e, tmp);
|
|
1640
|
+
} else {
|
|
1641
|
+
// debug("Order of group => '%zd'\n", mpz_sizeinbase(p, 2));
|
|
1642
|
+
// -y mod p
|
|
1643
|
+
debug("false case: return -y mod p.\n");
|
|
1644
|
+
mpz_neg(tmp, tmp);
|
|
1645
|
+
mpz_mod(tmp, tmp, p);
|
|
1646
|
+
debug("tmp...\n");
|
|
1647
|
+
print_mpz(tmp, 10);
|
|
1648
|
+
debug("p...\n");
|
|
1649
|
+
print_mpz(p, 10);
|
|
1650
|
+
|
|
1651
|
+
rop2 = createNewInteger();
|
|
1652
|
+
mpz_init(rop2->e);
|
|
1653
|
+
mpz_init_set(rop2->m, p);
|
|
1654
|
+
mpz_set(rop2->e, tmp);
|
|
1655
|
+
}
|
|
1656
|
+
mpz_clear(rop);
|
|
1657
|
+
mpz_clear(p);
|
|
1658
|
+
mpz_clear(exp);
|
|
1659
|
+
mpz_clear(tmp);
|
|
1660
|
+
return (PyObject *) rop2;
|
|
1661
|
+
}
|
|
1662
|
+
|
|
1663
|
+
EXIT_IF(TRUE, "invalid input types.");
|
|
1664
|
+
}
|
|
1665
|
+
|
|
1666
|
+
static PyObject *decode_message(PyObject *self, PyObject *args) {
|
|
1667
|
+
PyObject *element, *order, *order2;
|
|
1668
|
+
if (PyArg_ParseTuple(args, "OOO", &element, &order, &order2)) {
|
|
1669
|
+
if (PyInteger_Check(element) && PyInteger_Check(order)
|
|
1670
|
+
&& PyInteger_Check(order2)) {
|
|
1671
|
+
mpz_t p, q;
|
|
1672
|
+
Integer *elem, *pObj, *qObj; // mpz_init(elem);
|
|
1673
|
+
mpz_init(p);
|
|
1674
|
+
mpz_init(q);
|
|
1675
|
+
|
|
1676
|
+
// convert to mpz_t types...
|
|
1677
|
+
elem = (Integer *) element;
|
|
1678
|
+
pObj = (Integer *) order;
|
|
1679
|
+
qObj = (Integer *) order2;
|
|
1680
|
+
mpz_set(p, pObj->e);
|
|
1681
|
+
mpz_set(q, qObj->e);
|
|
1682
|
+
// test if elem <= q
|
|
1683
|
+
if (mpz_cmp(elem->e, q) <= 0) {
|
|
1684
|
+
debug("true case: g <= q.\n");
|
|
1685
|
+
mpz_sub_ui(elem->e, elem->e, 1);
|
|
1686
|
+
} else {
|
|
1687
|
+
debug("false case: g > q. so, y = -elem mod p.\n");
|
|
1688
|
+
// y = -elem mod p
|
|
1689
|
+
mpz_neg(elem->e, elem->e);
|
|
1690
|
+
mpz_mod(elem->e, elem->e, p);
|
|
1691
|
+
mpz_sub_ui(elem->e, elem->e, 1);
|
|
1692
|
+
}
|
|
1693
|
+
|
|
1694
|
+
size_t count = 0;
|
|
1695
|
+
unsigned char *Rop = (unsigned char *) mpz_export(NULL, &count, 1,
|
|
1696
|
+
sizeof(char), 0, 0, elem->e);
|
|
1697
|
+
debug("rop => '%s'\n", Rop);
|
|
1698
|
+
debug("count => '%zd'\n", count);
|
|
1699
|
+
|
|
1700
|
+
int size_Rop = Rop[0];
|
|
1701
|
+
char m[MSG_LEN+1];
|
|
1702
|
+
*m = '\0';
|
|
1703
|
+
strncat(m, (const char *)(Rop+1), size_Rop);
|
|
1704
|
+
|
|
1705
|
+
mpz_clear(p);
|
|
1706
|
+
mpz_clear(q);
|
|
1707
|
+
|
|
1708
|
+
PyObject *newObj = PyBytes_FromFormat("%s", m);
|
|
1709
|
+
free(Rop);
|
|
1710
|
+
return newObj;
|
|
1711
|
+
}
|
|
1712
|
+
}
|
|
1713
|
+
|
|
1714
|
+
return Py_BuildValue("i", FALSE);
|
|
1715
|
+
}
|
|
1716
|
+
|
|
1717
|
+
static PyObject *bitsize(PyObject *self, PyObject *args) {
|
|
1718
|
+
PyObject *object = NULL;
|
|
1719
|
+
int tmp_size;
|
|
1720
|
+
|
|
1721
|
+
if (PyArg_ParseTuple(args, "O", &object)) {
|
|
1722
|
+
if (_PyLong_Check(object)) {
|
|
1723
|
+
mpz_t tmp;
|
|
1724
|
+
mpz_init(tmp);
|
|
1725
|
+
longObjToMPZ(tmp, object);
|
|
1726
|
+
tmp_size = size(tmp);
|
|
1727
|
+
mpz_clear(tmp);
|
|
1728
|
+
return Py_BuildValue("i", tmp_size);
|
|
1729
|
+
} else if (PyInteger_Check(object)) {
|
|
1730
|
+
Integer *obj = (Integer *) object;
|
|
1731
|
+
if (obj->initialized) {
|
|
1732
|
+
tmp_size = size(obj->e);
|
|
1733
|
+
return Py_BuildValue("i", tmp_size);
|
|
1734
|
+
}
|
|
1735
|
+
}
|
|
1736
|
+
}
|
|
1737
|
+
PyErr_SetString(IntegerError, "invalid input type.");
|
|
1738
|
+
return NULL;
|
|
1739
|
+
}
|
|
1740
|
+
|
|
1741
|
+
static PyObject *testCoPrime(Integer *self, PyObject *arg) {
|
|
1742
|
+
mpz_t tmp, rop;
|
|
1743
|
+
int result = FALSE;
|
|
1744
|
+
|
|
1745
|
+
if (!self->initialized) {
|
|
1746
|
+
PyErr_SetString(IntegerError, "integer object not initialized.");
|
|
1747
|
+
return NULL;
|
|
1748
|
+
}
|
|
1749
|
+
|
|
1750
|
+
mpz_init(rop);
|
|
1751
|
+
if (arg != NULL) {
|
|
1752
|
+
PyObject *obj = PyNumber_Long(arg);
|
|
1753
|
+
if (obj != NULL) {
|
|
1754
|
+
mpz_init(tmp);
|
|
1755
|
+
longObjToMPZ(tmp, obj);
|
|
1756
|
+
mpz_gcd(rop, self->e, tmp);
|
|
1757
|
+
print_mpz(rop, 1);
|
|
1758
|
+
result = (mpz_cmp_ui(rop, 1) == 0) ? TRUE : FALSE;
|
|
1759
|
+
mpz_clear(tmp);
|
|
1760
|
+
Py_XDECREF(obj);
|
|
1761
|
+
}
|
|
1762
|
+
|
|
1763
|
+
} else {
|
|
1764
|
+
mpz_gcd(rop, self->e, self->m);
|
|
1765
|
+
print_mpz(rop, 1);
|
|
1766
|
+
result = (mpz_cmp_ui(rop, 1) == 0) ? TRUE : FALSE;
|
|
1767
|
+
}
|
|
1768
|
+
mpz_clear(rop);
|
|
1769
|
+
|
|
1770
|
+
if (result) {
|
|
1771
|
+
Py_INCREF(Py_True);
|
|
1772
|
+
return Py_True;
|
|
1773
|
+
} else {
|
|
1774
|
+
Py_INCREF(Py_False);
|
|
1775
|
+
return Py_False;
|
|
1776
|
+
}
|
|
1777
|
+
}
|
|
1778
|
+
|
|
1779
|
+
/*
|
|
1780
|
+
* Description: B.isCongruent(A) => A === B mod N. Test whether A is congruent to B mod N.
|
|
1781
|
+
*/
|
|
1782
|
+
static PyObject *testCongruency(Integer *self, PyObject *args) {
|
|
1783
|
+
PyObject *obj = NULL;
|
|
1784
|
+
|
|
1785
|
+
if (!self->initialized) {
|
|
1786
|
+
PyErr_SetString(IntegerError, "integer object not initialized.");
|
|
1787
|
+
return NULL;
|
|
1788
|
+
}
|
|
1789
|
+
|
|
1790
|
+
if (PyArg_ParseTuple(args, "O", &obj)) {
|
|
1791
|
+
if (_PyLong_Check(obj)) {
|
|
1792
|
+
PyObject *obj2 = PyNumber_Long(obj);
|
|
1793
|
+
if (obj2 != NULL) {
|
|
1794
|
+
mpz_t rop;
|
|
1795
|
+
mpz_init(rop);
|
|
1796
|
+
longObjToMPZ(rop, obj2);
|
|
1797
|
+
Py_XDECREF(obj2);
|
|
1798
|
+
if (mpz_congruent_p(rop, self->e, self->m) != 0) {
|
|
1799
|
+
mpz_clear(rop);
|
|
1800
|
+
Py_INCREF(Py_True);
|
|
1801
|
+
return Py_True;
|
|
1802
|
+
} else {
|
|
1803
|
+
mpz_clear(rop);
|
|
1804
|
+
Py_INCREF(Py_False);
|
|
1805
|
+
return Py_False;
|
|
1806
|
+
}
|
|
1807
|
+
}
|
|
1808
|
+
} else if (PyInteger_Check(obj)) {
|
|
1809
|
+
Integer *obj2 = (Integer *) obj;
|
|
1810
|
+
if (obj2->initialized && mpz_congruent_p(obj2->e, self->e, self->m)
|
|
1811
|
+
!= 0) {
|
|
1812
|
+
Py_INCREF(Py_True);
|
|
1813
|
+
return Py_True;
|
|
1814
|
+
} else {
|
|
1815
|
+
Py_XDECREF(Py_False);
|
|
1816
|
+
return Py_False;
|
|
1817
|
+
}
|
|
1818
|
+
}
|
|
1819
|
+
|
|
1820
|
+
}
|
|
1821
|
+
|
|
1822
|
+
EXIT_IF(TRUE, "need long or int value to test congruency.");
|
|
1823
|
+
}
|
|
1824
|
+
|
|
1825
|
+
static PyObject *legendre(PyObject *self, PyObject *args) {
|
|
1826
|
+
PyObject *obj1 = NULL, *obj2 = NULL;
|
|
1827
|
+
mpz_t a, p;
|
|
1828
|
+
mpz_init(a);
|
|
1829
|
+
mpz_init(p);
|
|
1830
|
+
|
|
1831
|
+
if (PyArg_ParseTuple(args, "OO", &obj1, &obj2)) {
|
|
1832
|
+
if (_PyLong_Check(obj1)) {
|
|
1833
|
+
longObjToMPZ(a, obj1);
|
|
1834
|
+
} else if (PyInteger_Check(obj1)) {
|
|
1835
|
+
Integer *tmp = (Integer *) obj1;
|
|
1836
|
+
mpz_set(a, tmp->e);
|
|
1837
|
+
}
|
|
1838
|
+
|
|
1839
|
+
if (_PyLong_Check(obj2)) {
|
|
1840
|
+
longObjToMPZ(p, obj2);
|
|
1841
|
+
} else if (PyInteger_Check(obj2)) {
|
|
1842
|
+
Integer *tmp2 = (Integer *) obj2;
|
|
1843
|
+
mpz_set(p, tmp2->e);
|
|
1844
|
+
}
|
|
1845
|
+
|
|
1846
|
+
// make sure a,p have been set
|
|
1847
|
+
if (mpz_cmp_ui(a, 0) != 0 && mpz_cmp_ui(p, 0) != 0) {
|
|
1848
|
+
// make sure p is odd and positive prime number
|
|
1849
|
+
int prop_p = mpz_probab_prime_p(p, MAX_RUN);
|
|
1850
|
+
if (mpz_odd_p(p) > 0 && prop_p > 0) {
|
|
1851
|
+
return Py_BuildValue("i", mpz_legendre(a, p));
|
|
1852
|
+
} else {
|
|
1853
|
+
return Py_BuildValue("i", FALSE);
|
|
1854
|
+
}
|
|
1855
|
+
}
|
|
1856
|
+
}
|
|
1857
|
+
|
|
1858
|
+
EXIT_IF(TRUE, "invalid input.");
|
|
1859
|
+
}
|
|
1860
|
+
|
|
1861
|
+
static PyObject *gcdCall(PyObject *self, PyObject *args) {
|
|
1862
|
+
PyObject *obj1 = NULL, *obj2 = NULL;
|
|
1863
|
+
mpz_t op1, op2;
|
|
1864
|
+
|
|
1865
|
+
if (PyArg_ParseTuple(args, "OO", &obj1, &obj2)) {
|
|
1866
|
+
if (_PyLong_Check(obj1)) {
|
|
1867
|
+
mpz_init(op1);
|
|
1868
|
+
longObjToMPZ(op1, obj1);
|
|
1869
|
+
} else if (PyInteger_Check(obj1)) {
|
|
1870
|
+
mpz_init(op1);
|
|
1871
|
+
Integer *tmp = (Integer *) obj1;
|
|
1872
|
+
mpz_set(op1, tmp->e);
|
|
1873
|
+
} else {
|
|
1874
|
+
ErrorMsg("invalid argument type: 1");
|
|
1875
|
+
}
|
|
1876
|
+
|
|
1877
|
+
if (_PyLong_Check(obj2)) {
|
|
1878
|
+
mpz_init(op2);
|
|
1879
|
+
longObjToMPZ(op2, obj2);
|
|
1880
|
+
} else if (PyInteger_Check(obj2)) {
|
|
1881
|
+
mpz_init(op2);
|
|
1882
|
+
Integer *tmp = (Integer *) obj2;
|
|
1883
|
+
mpz_set(op2, tmp->e);
|
|
1884
|
+
} else {
|
|
1885
|
+
mpz_clear(op1);
|
|
1886
|
+
ErrorMsg("invalid argument type: 2");
|
|
1887
|
+
}
|
|
1888
|
+
|
|
1889
|
+
Integer *rop = createNewInteger();
|
|
1890
|
+
mpz_init(rop->e);
|
|
1891
|
+
mpz_init(rop->m);
|
|
1892
|
+
mpz_gcd(rop->e, op1, op2);
|
|
1893
|
+
mpz_clear(op1);
|
|
1894
|
+
mpz_clear(op2);
|
|
1895
|
+
return (PyObject *) rop;
|
|
1896
|
+
}
|
|
1897
|
+
|
|
1898
|
+
EXIT_IF(TRUE, "invalid input.");
|
|
1899
|
+
}
|
|
1900
|
+
|
|
1901
|
+
static PyObject *lcmCall(PyObject *self, PyObject *args) {
|
|
1902
|
+
PyObject *obj1 = NULL, *obj2 = NULL;
|
|
1903
|
+
mpz_t op1, op2;
|
|
1904
|
+
|
|
1905
|
+
if (PyArg_ParseTuple(args, "OO", &obj1, &obj2)) {
|
|
1906
|
+
if (_PyLong_Check(obj1)) {
|
|
1907
|
+
mpz_init(op1);
|
|
1908
|
+
longObjToMPZ(op1, obj1);
|
|
1909
|
+
} else if (PyInteger_Check(obj1)) {
|
|
1910
|
+
mpz_init(op1);
|
|
1911
|
+
Integer *tmp = (Integer *) obj1;
|
|
1912
|
+
mpz_set(op1, tmp->e);
|
|
1913
|
+
} else {
|
|
1914
|
+
EXIT_IF(TRUE, "invalid argument type: 1");
|
|
1915
|
+
}
|
|
1916
|
+
|
|
1917
|
+
if (_PyLong_Check(obj2)) {
|
|
1918
|
+
mpz_init(op2);
|
|
1919
|
+
longObjToMPZ(op2, obj2);
|
|
1920
|
+
} else if (PyInteger_Check(obj2)) {
|
|
1921
|
+
mpz_init(op2);
|
|
1922
|
+
Integer *tmp = (Integer *) obj2;
|
|
1923
|
+
mpz_set(op2, tmp->e);
|
|
1924
|
+
} else {
|
|
1925
|
+
mpz_clear(op1);
|
|
1926
|
+
EXIT_IF(TRUE, "invalid argument type: 2");
|
|
1927
|
+
}
|
|
1928
|
+
|
|
1929
|
+
Integer *rop = createNewInteger();
|
|
1930
|
+
mpz_init(rop->e);
|
|
1931
|
+
mpz_init(rop->m);
|
|
1932
|
+
mpz_lcm(rop->e, op1, op2);
|
|
1933
|
+
mpz_clear(op1);
|
|
1934
|
+
mpz_clear(op2);
|
|
1935
|
+
return (PyObject *) rop;
|
|
1936
|
+
}
|
|
1937
|
+
|
|
1938
|
+
EXIT_IF(TRUE, "invalid input.");
|
|
1939
|
+
}
|
|
1940
|
+
|
|
1941
|
+
static PyObject *serialize(PyObject *self, PyObject *args) {
|
|
1942
|
+
Integer *obj = NULL;
|
|
1943
|
+
int isNeg;
|
|
1944
|
+
|
|
1945
|
+
if (!PyArg_ParseTuple(args, "O", &obj)) {
|
|
1946
|
+
ErrorMsg("invalid argument");
|
|
1947
|
+
}
|
|
1948
|
+
if(!PyInteger_Check(obj)) EXIT_IF(TRUE, "not a valid element object.");
|
|
1949
|
+
|
|
1950
|
+
// export the object first
|
|
1951
|
+
size_t count1 = 0, count2 = 0;
|
|
1952
|
+
char *base64_rop = NULL, *base64_rop2 = NULL;
|
|
1953
|
+
PyObject *bytes1 = NULL, *bytes2 = NULL;
|
|
1954
|
+
// if (mpz_sgn(obj->e) > 0) {
|
|
1955
|
+
uint8_t *rop = (uint8_t *) mpz_export(NULL, &count1, 1, sizeof(char),
|
|
1956
|
+
0, 0, obj->e);
|
|
1957
|
+
// convert string to base64 encoding
|
|
1958
|
+
size_t length = 0;
|
|
1959
|
+
base64_rop = NewBase64Encode(rop, count1, FALSE, &length);
|
|
1960
|
+
isNeg = mpz_sgn(obj->e) < 0 ? TRUE : FALSE;
|
|
1961
|
+
// convert to bytes (length : base64 integer)
|
|
1962
|
+
bytes1 = PyBytes_FromFormat("%d:%d:%s:", isNeg, (int) length,
|
|
1963
|
+
(const char *) base64_rop);
|
|
1964
|
+
free(base64_rop);
|
|
1965
|
+
free(rop);
|
|
1966
|
+
// }
|
|
1967
|
+
|
|
1968
|
+
if (mpz_sgn(obj->m) > 0) {
|
|
1969
|
+
uint8_t *rop2 = (uint8_t *) mpz_export(NULL, &count2, 1, sizeof(char),
|
|
1970
|
+
0, 0, obj->m);
|
|
1971
|
+
size_t length2 = 0;
|
|
1972
|
+
base64_rop2 = NewBase64Encode(rop2, count2, FALSE, &length2);
|
|
1973
|
+
// convert to bytes
|
|
1974
|
+
bytes2 = PyBytes_FromFormat("%d:%s:", (int) length2,
|
|
1975
|
+
(const char *) base64_rop2);
|
|
1976
|
+
free(base64_rop2);
|
|
1977
|
+
free(rop2);
|
|
1978
|
+
}
|
|
1979
|
+
|
|
1980
|
+
if (bytes2 != NULL && bytes1 != NULL) {
|
|
1981
|
+
PyBytes_ConcatAndDel(&bytes1, bytes2);
|
|
1982
|
+
return bytes1;
|
|
1983
|
+
} else if (bytes1 != NULL) {
|
|
1984
|
+
return bytes1;
|
|
1985
|
+
} else {
|
|
1986
|
+
EXIT_IF(TRUE, "invalid integer object.");
|
|
1987
|
+
}
|
|
1988
|
+
}
|
|
1989
|
+
|
|
1990
|
+
void deserialize_helper(int length, char *encoded_value, mpz_t target)
|
|
1991
|
+
{
|
|
1992
|
+
debug("encoded_value len => '%zd'", strlen(encoded_value));
|
|
1993
|
+
|
|
1994
|
+
size_t deserialized_len = 0;
|
|
1995
|
+
uint8_t *buf = NewBase64Decode((const char *) encoded_value, length, &deserialized_len);
|
|
1996
|
+
|
|
1997
|
+
mpz_import(target, deserialized_len, 1, sizeof(buf[0]), 0, 0, buf);
|
|
1998
|
+
free(buf);
|
|
1999
|
+
}
|
|
2000
|
+
|
|
2001
|
+
static PyObject *deserialize(PyObject *self, PyObject *args) {
|
|
2002
|
+
PyObject *bytesObj = NULL;
|
|
2003
|
+
|
|
2004
|
+
if (!PyArg_ParseTuple(args, "O", &bytesObj)) {
|
|
2005
|
+
EXIT_IF(TRUE, "invalid argument.");
|
|
2006
|
+
}
|
|
2007
|
+
|
|
2008
|
+
uint8_t *serial_buf2 = (uint8_t *) PyBytes_AsString(bytesObj);
|
|
2009
|
+
int serial_buf2_len = strlen((char *) serial_buf2);
|
|
2010
|
+
uint8_t serial_buf[serial_buf2_len + 1];
|
|
2011
|
+
memset(serial_buf, 0, serial_buf2_len + 1);
|
|
2012
|
+
memcpy(serial_buf, serial_buf2, serial_buf2_len);
|
|
2013
|
+
/* get integer value */
|
|
2014
|
+
char delim[] = ":";
|
|
2015
|
+
char *token = NULL;
|
|
2016
|
+
token = strtok((char *) serial_buf, delim);
|
|
2017
|
+
// positive or negative
|
|
2018
|
+
int isNeg = atoi((const char *) token);
|
|
2019
|
+
token = strtok(NULL, delim);
|
|
2020
|
+
// length
|
|
2021
|
+
int int_len = atoi((const char *) token);
|
|
2022
|
+
debug("length => '%d'\n", int_len);
|
|
2023
|
+
mpz_t x,m;
|
|
2024
|
+
mpz_init(x);
|
|
2025
|
+
mpz_init(m);
|
|
2026
|
+
|
|
2027
|
+
// parse the first half of the bytes/str object
|
|
2028
|
+
token = strtok(NULL, delim);
|
|
2029
|
+
debug("encoded value x => '%s'\n", token);
|
|
2030
|
+
if(token != NULL) {
|
|
2031
|
+
deserialize_helper(int_len, token, x);
|
|
2032
|
+
debug("decoded value x => ");
|
|
2033
|
+
print_mpz(x, 10);
|
|
2034
|
+
}
|
|
2035
|
+
|
|
2036
|
+
// parse modulus (if indeed modular integer)
|
|
2037
|
+
token = strtok(NULL, delim);
|
|
2038
|
+
if(token != NULL) {
|
|
2039
|
+
int_len = atoi((const char *) token);
|
|
2040
|
+
token = strtok(NULL, delim);
|
|
2041
|
+
deserialize_helper(int_len, token, m);
|
|
2042
|
+
debug("decoded value m => ");
|
|
2043
|
+
print_mpz(m, 10);
|
|
2044
|
+
}
|
|
2045
|
+
|
|
2046
|
+
Integer *obj = NULL;
|
|
2047
|
+
if(mpz_sgn(m) > 0) {
|
|
2048
|
+
obj = createNewInteger();
|
|
2049
|
+
mpz_init(obj->e);
|
|
2050
|
+
mpz_init_set(obj->m, m);
|
|
2051
|
+
}
|
|
2052
|
+
else {
|
|
2053
|
+
obj = createNewInteger();
|
|
2054
|
+
mpz_init(obj->e);
|
|
2055
|
+
mpz_init(obj->m);
|
|
2056
|
+
}
|
|
2057
|
+
mpz_set(obj->e, x);
|
|
2058
|
+
if(isNeg) mpz_neg(obj->e, obj->e);
|
|
2059
|
+
|
|
2060
|
+
mpz_clear(x);
|
|
2061
|
+
mpz_clear(m);
|
|
2062
|
+
return (PyObject *) obj;
|
|
2063
|
+
}
|
|
2064
|
+
|
|
2065
|
+
// class method for conversion
|
|
2066
|
+
// integer.toBytes(x) => b'blah blah'
|
|
2067
|
+
static PyObject *toBytes(PyObject *self, PyObject *args) {
|
|
2068
|
+
Integer *intObj = NULL;
|
|
2069
|
+
|
|
2070
|
+
if (PyInteger_Check(args)) {
|
|
2071
|
+
intObj = (Integer *) args;
|
|
2072
|
+
size_t count = 0;
|
|
2073
|
+
unsigned char *Rop = (unsigned char *) mpz_export(NULL, &count, 1,
|
|
2074
|
+
sizeof(char), 0, 0, intObj->e);
|
|
2075
|
+
debug("Rop => '%s', len =>'%zd'\n", Rop, count);
|
|
2076
|
+
PyObject *newObj = PyBytes_FromStringAndSize((const char *) Rop, (Py_ssize_t) count);
|
|
2077
|
+
free(Rop);
|
|
2078
|
+
return newObj;
|
|
2079
|
+
}
|
|
2080
|
+
|
|
2081
|
+
EXIT_IF(TRUE, "invalid type.");
|
|
2082
|
+
}
|
|
2083
|
+
|
|
2084
|
+
// class method for conversion for modular integer to an integer
|
|
2085
|
+
// integer.toInt(x mod Y) => x
|
|
2086
|
+
static PyObject *toInt(PyObject *self, PyObject *args) {
|
|
2087
|
+
Integer *intObj = NULL;
|
|
2088
|
+
|
|
2089
|
+
if (PyInteger_Check(args)) {
|
|
2090
|
+
intObj = (Integer *) args;
|
|
2091
|
+
Integer *rop = createNewInteger();
|
|
2092
|
+
mpz_init_set(rop->e, intObj->e);
|
|
2093
|
+
mpz_init(rop->m);
|
|
2094
|
+
|
|
2095
|
+
return (PyObject *) rop;
|
|
2096
|
+
}
|
|
2097
|
+
|
|
2098
|
+
EXIT_IF(TRUE, "not a charm integer type.");
|
|
2099
|
+
}
|
|
2100
|
+
|
|
2101
|
+
static PyObject *getMod(PyObject *self, PyObject *args) {
|
|
2102
|
+
Integer *intObj = NULL;
|
|
2103
|
+
|
|
2104
|
+
if (PyInteger_Check(args)) {
|
|
2105
|
+
intObj = (Integer *) args;
|
|
2106
|
+
Integer *rop = createNewInteger();
|
|
2107
|
+
mpz_init_set(rop->e, intObj->m);
|
|
2108
|
+
mpz_init(rop->m);
|
|
2109
|
+
return (PyObject *) rop;
|
|
2110
|
+
}
|
|
2111
|
+
|
|
2112
|
+
EXIT_IF(TRUE, "not a charm integer type.");
|
|
2113
|
+
}
|
|
2114
|
+
|
|
2115
|
+
static PyObject *Integer_xor(PyObject *self, PyObject *other) {
|
|
2116
|
+
Integer *rop = NULL, *op1 = NULL, *op2 = NULL;
|
|
2117
|
+
|
|
2118
|
+
if (PyInteger_Check(self))
|
|
2119
|
+
op1 = (Integer *) self;
|
|
2120
|
+
if (PyInteger_Check(other))
|
|
2121
|
+
op2 = (Integer *) other;
|
|
2122
|
+
|
|
2123
|
+
EXIT_IF(op1 == NULL || op2 == NULL, "both types are not of charm integer types.");
|
|
2124
|
+
if (PyInteger_Init(op1, op2)) {
|
|
2125
|
+
rop = createNewInteger();
|
|
2126
|
+
mpz_init(rop->e);
|
|
2127
|
+
mpz_init(rop->m);
|
|
2128
|
+
mpz_xor(rop->e, op1->e, op2->e);
|
|
2129
|
+
return (PyObject *) rop;
|
|
2130
|
+
}
|
|
2131
|
+
|
|
2132
|
+
EXIT_IF(TRUE, "objects not initialized properly.");
|
|
2133
|
+
}
|
|
2134
|
+
|
|
2135
|
+
#ifdef BENCHMARK_ENABLED
|
|
2136
|
+
#define BenchmarkIdentifier 3
|
|
2137
|
+
|
|
2138
|
+
#if defined(__APPLE__)
|
|
2139
|
+
// benchmark new
|
|
2140
|
+
PyObject *Benchmark_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
|
|
2141
|
+
{
|
|
2142
|
+
Benchmark *self;
|
|
2143
|
+
self = (Benchmark *)type->tp_alloc(type, 0);
|
|
2144
|
+
if(self != NULL) {
|
|
2145
|
+
self->bench_initialized = FALSE;
|
|
2146
|
+
self->bench_inprogress = FALSE; // false until we StartBenchmark( ... )
|
|
2147
|
+
self->op_add = self->op_sub = self->op_mult = 0;
|
|
2148
|
+
self->op_div = self->op_exp = self->op_pair = 0;
|
|
2149
|
+
self->cpu_time_ms = self->real_time_ms = 0.0;
|
|
2150
|
+
self->cpu_option = self->real_option = FALSE;
|
|
2151
|
+
debug("Creating new benchmark object.\n");
|
|
2152
|
+
}
|
|
2153
|
+
return (PyObject *) self;
|
|
2154
|
+
}
|
|
2155
|
+
|
|
2156
|
+
// benchmark init
|
|
2157
|
+
int Benchmark_init(Benchmark *self, PyObject *args, PyObject *kwds)
|
|
2158
|
+
{
|
|
2159
|
+
return 0;
|
|
2160
|
+
}
|
|
2161
|
+
// benchmark dealloc
|
|
2162
|
+
void Benchmark_dealloc(Benchmark *self) {
|
|
2163
|
+
debug("Releasing benchmark object.\n");
|
|
2164
|
+
Py_TYPE(self)->tp_free((PyObject*)self);
|
|
2165
|
+
}
|
|
2166
|
+
|
|
2167
|
+
PyTypeObject BenchmarkType = {
|
|
2168
|
+
PyVarObject_HEAD_INIT(NULL, 0)
|
|
2169
|
+
"profile.Benchmark", /*tp_name*/
|
|
2170
|
+
sizeof(Benchmark), /*tp_basicsize*/
|
|
2171
|
+
0, /*tp_itemsize*/
|
|
2172
|
+
(destructor)Benchmark_dealloc, /*tp_dealloc*/
|
|
2173
|
+
0, /*tp_print*/
|
|
2174
|
+
0, /*tp_getattr*/
|
|
2175
|
+
0, /*tp_setattr*/
|
|
2176
|
+
0, /*tp_reserved*/
|
|
2177
|
+
0, /*tp_repr*/
|
|
2178
|
+
0, /*tp_as_number*/
|
|
2179
|
+
0, /*tp_as_sequence*/
|
|
2180
|
+
0, /*tp_as_mapping*/
|
|
2181
|
+
0, /*tp_hash */
|
|
2182
|
+
0, /*tp_call*/
|
|
2183
|
+
0, /*tp_str*/
|
|
2184
|
+
0, /*tp_getattro*/
|
|
2185
|
+
0, /*tp_setattro*/
|
|
2186
|
+
0, /*tp_as_buffer*/
|
|
2187
|
+
Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /*tp_flags*/
|
|
2188
|
+
"Benchmark objects", /* tp_doc */
|
|
2189
|
+
0, /* tp_traverse */
|
|
2190
|
+
0, /* tp_clear */
|
|
2191
|
+
0, /* tp_richcompare */
|
|
2192
|
+
0, /* tp_weaklistoffset */
|
|
2193
|
+
0, /* tp_iter */
|
|
2194
|
+
0, /* tp_iternext */
|
|
2195
|
+
0, /* tp_methods */
|
|
2196
|
+
0, /* tp_members */
|
|
2197
|
+
0, /* tp_getset */
|
|
2198
|
+
0, /* tp_base */
|
|
2199
|
+
0, /* tp_dict */
|
|
2200
|
+
0, /* tp_descr_get */
|
|
2201
|
+
0, /* tp_descr_set */
|
|
2202
|
+
0, /* tp_dictoffset */
|
|
2203
|
+
(initproc)Benchmark_init, /* tp_init */
|
|
2204
|
+
0, /* tp_alloc */
|
|
2205
|
+
Benchmark_new, /* tp_new */
|
|
2206
|
+
};
|
|
2207
|
+
|
|
2208
|
+
#endif
|
|
2209
|
+
|
|
2210
|
+
PyObject *InitBenchmark(PyObject *self, PyObject *args) {
|
|
2211
|
+
Benchmark *b = GETSTATE(self)->dBench;
|
|
2212
|
+
if(b == NULL) {
|
|
2213
|
+
GETSTATE(self)->dBench = PyObject_New(Benchmark, &BenchmarkType);
|
|
2214
|
+
if(GETSTATE(self)->dBench == NULL) {
|
|
2215
|
+
PyErr_SetString(IntegerError, "InitBenchmark - out of memory.");
|
|
2216
|
+
return NULL;
|
|
2217
|
+
}
|
|
2218
|
+
Py_INCREF(GETSTATE(self)->dBench);
|
|
2219
|
+
tmpBench = GETSTATE(self)->dBench;
|
|
2220
|
+
Benchmark *dBench = GETSTATE(self)->dBench;
|
|
2221
|
+
PyClearBenchmark(dBench);
|
|
2222
|
+
dBench->bench_initialized = TRUE;
|
|
2223
|
+
dBench->bench_inprogress = FALSE;
|
|
2224
|
+
dBench->identifier = BenchmarkIdentifier;
|
|
2225
|
+
Py_RETURN_TRUE;
|
|
2226
|
+
}
|
|
2227
|
+
else if(b != NULL && b->bench_initialized == FALSE) {
|
|
2228
|
+
debug("%s: bench init: '%i'\n", __FUNCTION__, b->bench_initialized);
|
|
2229
|
+
debug("%s: bench id set: '%i'\n", __FUNCTION__, b->identifier);
|
|
2230
|
+
b->bench_initialized = TRUE;
|
|
2231
|
+
b->identifier = BenchmarkIdentifier;
|
|
2232
|
+
debug("Initialized benchmark object.\n");
|
|
2233
|
+
Py_RETURN_TRUE;
|
|
2234
|
+
}
|
|
2235
|
+
else if(b != NULL && b->bench_inprogress == FALSE && b->bench_initialized == TRUE) {
|
|
2236
|
+
PyClearBenchmark(b);
|
|
2237
|
+
b->bench_initialized = TRUE;
|
|
2238
|
+
b->bench_inprogress = FALSE;
|
|
2239
|
+
b->identifier = BenchmarkIdentifier;
|
|
2240
|
+
Py_RETURN_TRUE;
|
|
2241
|
+
}
|
|
2242
|
+
else if(b != NULL && b->bench_inprogress == TRUE) {
|
|
2243
|
+
printf("Benchmark in progress.\n");
|
|
2244
|
+
}
|
|
2245
|
+
|
|
2246
|
+
debug("Benchmark already initialized.\n");
|
|
2247
|
+
Py_RETURN_FALSE;
|
|
2248
|
+
}
|
|
2249
|
+
|
|
2250
|
+
PyObject *StartBenchmark(PyObject *self, PyObject *args) {
|
|
2251
|
+
PyObject *list = NULL;
|
|
2252
|
+
Benchmark *b = GETSTATE(self)->dBench;
|
|
2253
|
+
if(!PyArg_ParseTuple(args, "O", &list)) {
|
|
2254
|
+
PyErr_SetString(IntegerError, "StartBenchmark - invalid argument.");
|
|
2255
|
+
return NULL;
|
|
2256
|
+
}
|
|
2257
|
+
if(b == NULL) {
|
|
2258
|
+
PyErr_SetString(IntegerError, "uninitialized benchmark object.");
|
|
2259
|
+
return NULL;
|
|
2260
|
+
}
|
|
2261
|
+
else if(PyList_Check(list) && b->bench_initialized == TRUE && b->bench_inprogress == FALSE && b->identifier == BenchmarkIdentifier) {
|
|
2262
|
+
debug("%s: bench id: '%i'\n", __FUNCTION__, b->identifier);
|
|
2263
|
+
size_t size = PyList_Size(list);
|
|
2264
|
+
PyStartBenchmark(b, list, size);
|
|
2265
|
+
debug("list size => %zd\n", size);
|
|
2266
|
+
debug("benchmark enabled and initialized!\n");
|
|
2267
|
+
Py_RETURN_TRUE;
|
|
2268
|
+
}
|
|
2269
|
+
Py_RETURN_FALSE;
|
|
2270
|
+
}
|
|
2271
|
+
|
|
2272
|
+
PyObject *EndBenchmark(PyObject *self, PyObject *args) {
|
|
2273
|
+
Benchmark *b = GETSTATE(self)->dBench;
|
|
2274
|
+
if(b != NULL) {
|
|
2275
|
+
debug("%s: bench init: '%i'\n", __FUNCTION__, b->bench_initialized);
|
|
2276
|
+
debug("%s: bench id: '%i'\n", __FUNCTION__, b->identifier);
|
|
2277
|
+
if(b->bench_initialized == TRUE && b->bench_inprogress == TRUE && b->identifier == BenchmarkIdentifier) {
|
|
2278
|
+
PyEndBenchmark(b);
|
|
2279
|
+
debug("%s: bench id: '%i'\n", __FUNCTION__, b->identifier);
|
|
2280
|
+
Py_RETURN_TRUE;
|
|
2281
|
+
}
|
|
2282
|
+
}
|
|
2283
|
+
|
|
2284
|
+
PyErr_SetString(IntegerError, "uninitialized benchmark object.");
|
|
2285
|
+
return NULL;
|
|
2286
|
+
}
|
|
2287
|
+
|
|
2288
|
+
static PyObject *GetBenchmark(PyObject *self, PyObject *args) {
|
|
2289
|
+
char *opt = NULL;
|
|
2290
|
+
Benchmark *b = GETSTATE(self)->dBench;
|
|
2291
|
+
if(!PyArg_ParseTuple(args, "s", &opt))
|
|
2292
|
+
{
|
|
2293
|
+
PyErr_SetString(IntegerError, "GetBenchmark - invalid argument.");
|
|
2294
|
+
return NULL;
|
|
2295
|
+
}
|
|
2296
|
+
|
|
2297
|
+
if(b == NULL) {
|
|
2298
|
+
PyErr_SetString(IntegerError, "uninitialized benchmark object.");
|
|
2299
|
+
return NULL;
|
|
2300
|
+
}
|
|
2301
|
+
else if(b->bench_initialized == TRUE && b->bench_inprogress == FALSE && b->identifier == BenchmarkIdentifier) {
|
|
2302
|
+
return Retrieve_result(b, opt);
|
|
2303
|
+
}
|
|
2304
|
+
Py_RETURN_FALSE;
|
|
2305
|
+
}
|
|
2306
|
+
|
|
2307
|
+
static PyObject *GetAllBenchmarks(PyObject *self, PyObject *args) {
|
|
2308
|
+
Benchmark *b = GETSTATE(self)->dBench;
|
|
2309
|
+
if(b != NULL) {
|
|
2310
|
+
debug("%s: bench id: '%i'\n", __FUNCTION__, b->identifier);
|
|
2311
|
+
if(b->bench_initialized == TRUE && b->bench_inprogress == FALSE && b->identifier == BenchmarkIdentifier)
|
|
2312
|
+
return GetResults(b);
|
|
2313
|
+
debug("Invalid benchmark identifier.\n");
|
|
2314
|
+
}
|
|
2315
|
+
|
|
2316
|
+
PyErr_SetString(IntegerError, "uninitialized benchmark object.");
|
|
2317
|
+
return NULL;
|
|
2318
|
+
}
|
|
2319
|
+
|
|
2320
|
+
#endif
|
|
2321
|
+
|
|
2322
|
+
PyMethodDef Integer_methods[] = {
|
|
2323
|
+
{ "set", (PyCFunction) Integer_set, METH_VARARGS, "initialize with another integer object." },
|
|
2324
|
+
#if PY_MINOR_VERSION <= 7
|
|
2325
|
+
{ "isCoPrime", (PyCFunction) testCoPrime, METH_O | METH_NOARGS, "determine whether two integers a and b are relatively prime." },
|
|
2326
|
+
#else
|
|
2327
|
+
{ "isCoPrime", (PyCFunction) testCoPrime, METH_O, "determine whether two integers a and b are relatively prime." },
|
|
2328
|
+
#endif
|
|
2329
|
+
{ "isCongruent", (PyCFunction) testCongruency, METH_VARARGS, "determine whether two integers are congruent mod n." },
|
|
2330
|
+
// { "reduce", (PyCFunction) Integer_reduce, METH_NOARGS, "reduce an integer object modulo N." },
|
|
2331
|
+
{ NULL }
|
|
2332
|
+
};
|
|
2333
|
+
|
|
2334
|
+
PyNumberMethods integer_number = {
|
|
2335
|
+
Integer_add, /* nb_add */
|
|
2336
|
+
Integer_sub, /* nb_subtract */
|
|
2337
|
+
Integer_mul, /* nb_multiply */
|
|
2338
|
+
Integer_remainder, /* nb_remainder */
|
|
2339
|
+
0, /* nb_divmod */
|
|
2340
|
+
Integer_pow, /* nb_power */
|
|
2341
|
+
0, /* nb_negative */
|
|
2342
|
+
0, /* nb_positive */
|
|
2343
|
+
0, /* nb_absolute */
|
|
2344
|
+
0, /* nb_bool */
|
|
2345
|
+
(unaryfunc) Integer_invert, /* nb_invert */
|
|
2346
|
+
0, /* nb_lshift */
|
|
2347
|
+
0, /* nb_rshift */
|
|
2348
|
+
0, /* nb_and */
|
|
2349
|
+
Integer_xor, /* nb_xor */
|
|
2350
|
+
0, /* nb_or */
|
|
2351
|
+
(unaryfunc) Integer_long, /* nb_int */
|
|
2352
|
+
0, /* nb_reserved */
|
|
2353
|
+
0, /* nb_float */
|
|
2354
|
+
Integer_add, /* nb_inplace_add */
|
|
2355
|
+
Integer_sub, /* nb_inplace_subtract */
|
|
2356
|
+
Integer_mul, /* nb_inplace_multiply */
|
|
2357
|
+
Integer_remainder, /* nb_inplace_remainder */
|
|
2358
|
+
Integer_pow, /* nb_inplace_power */
|
|
2359
|
+
0, /* nb_inplace_lshift */
|
|
2360
|
+
0, /* nb_inplace_rshift */
|
|
2361
|
+
0, /* nb_inplace_and */
|
|
2362
|
+
0, /* nb_inplace_xor */
|
|
2363
|
+
0, /* nb_inplace_or */
|
|
2364
|
+
0, /* nb_floor_divide */
|
|
2365
|
+
Integer_div, /* nb_true_divide */
|
|
2366
|
+
0, /* nb_inplace_floor_divide */
|
|
2367
|
+
Integer_div, /* nb_inplace_true_divide */
|
|
2368
|
+
0, /* nb_index */
|
|
2369
|
+
};
|
|
2370
|
+
|
|
2371
|
+
PyTypeObject IntegerType = {
|
|
2372
|
+
PyVarObject_HEAD_INIT(NULL, 0)
|
|
2373
|
+
"integer.Element", /*tp_name*/
|
|
2374
|
+
sizeof(Integer), /*tp_basicsize*/
|
|
2375
|
+
0, /*tp_itemsize*/
|
|
2376
|
+
(destructor)Integer_dealloc, /*tp_dealloc*/
|
|
2377
|
+
0, /*tp_print*/
|
|
2378
|
+
0, /*tp_getattr*/
|
|
2379
|
+
0, /*tp_setattr*/
|
|
2380
|
+
0, /*tp_reserved*/
|
|
2381
|
+
(reprfunc)Integer_print, /*tp_repr*/
|
|
2382
|
+
&integer_number, /*tp_as_number*/
|
|
2383
|
+
0, /*tp_as_sequence*/
|
|
2384
|
+
0, /*tp_as_mapping*/
|
|
2385
|
+
0, /*tp_hash */
|
|
2386
|
+
0, /*tp_call*/
|
|
2387
|
+
0, /*tp_str*/
|
|
2388
|
+
0, /*tp_getattro*/
|
|
2389
|
+
0, /*tp_setattro*/
|
|
2390
|
+
0, /*tp_as_buffer*/
|
|
2391
|
+
Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /*tp_flags*/
|
|
2392
|
+
"Modular Integer objects", /* tp_doc */
|
|
2393
|
+
0, /* tp_traverse */
|
|
2394
|
+
0, /* tp_clear */
|
|
2395
|
+
Integer_equals, /* tp_richcompare */
|
|
2396
|
+
0, /* tp_weaklistoffset */
|
|
2397
|
+
0, /* tp_iter */
|
|
2398
|
+
0, /* tp_iternext */
|
|
2399
|
+
Integer_methods, /* tp_methods */
|
|
2400
|
+
0, /* tp_members */
|
|
2401
|
+
0, /* tp_getset */
|
|
2402
|
+
0, /* tp_base */
|
|
2403
|
+
0, /* tp_dict */
|
|
2404
|
+
0, /* tp_descr_get */
|
|
2405
|
+
0, /* tp_descr_set */
|
|
2406
|
+
0, /* tp_dictoffset */
|
|
2407
|
+
(initproc)Integer_init, /* tp_init */
|
|
2408
|
+
0, /* tp_alloc */
|
|
2409
|
+
Integer_new, /* tp_new */
|
|
2410
|
+
};
|
|
2411
|
+
|
|
2412
|
+
/* global module methods (include isPrime, randomPrime, etc. here). */
|
|
2413
|
+
PyMethodDef module_methods[] = {
|
|
2414
|
+
{ "randomBits", (PyCFunction) genRandomBits, METH_VARARGS, "generate a random number of bits from 0 to 2^n-1." },
|
|
2415
|
+
{ "random", (PyCFunction) genRandom, METH_VARARGS, "generate a random number in range of 0 to n-1 where n is large number." },
|
|
2416
|
+
{ "randomPrime", (PyCFunction) genRandomPrime, METH_VARARGS, "generate a probabilistic random prime number that is n-bits." },
|
|
2417
|
+
{ "isPrime", (PyCFunction) testPrimality, METH_O, "probabilistic algorithm to whether a given integer is prime." },
|
|
2418
|
+
{ "encode", (PyCFunction) encode_message, METH_VARARGS, "encode a message as a group element where p = 2*q + 1 only." },
|
|
2419
|
+
{ "decode", (PyCFunction) decode_message, METH_VARARGS, "decode a message from a group element where p = 2*q + 1 to a message." },
|
|
2420
|
+
{ "hashInt", (PyCFunction) Integer_hash, METH_VARARGS, "hash to group elements in which p = 2*q+1." },
|
|
2421
|
+
{ "bitsize", (PyCFunction) bitsize, METH_VARARGS, "determine how many bits required to represent a given value." },
|
|
2422
|
+
{ "legendre", (PyCFunction) legendre, METH_VARARGS, "given a and a positive prime p compute the legendre symbol." },
|
|
2423
|
+
{ "gcd", (PyCFunction) gcdCall, METH_VARARGS, "compute the gcd of two integers a and b." },
|
|
2424
|
+
{ "lcm", (PyCFunction) lcmCall, METH_VARARGS, "compute the lcd of two integers a and b." },
|
|
2425
|
+
{ "serialize", (PyCFunction) serialize, METH_VARARGS, "Serialize an integer type into bytes." },
|
|
2426
|
+
{ "deserialize", (PyCFunction) deserialize, METH_VARARGS, "De-serialize an bytes object into an integer object" },
|
|
2427
|
+
#ifdef BENCHMARK_ENABLED
|
|
2428
|
+
{ "InitBenchmark", (PyCFunction) InitBenchmark, METH_NOARGS, "Initialize a benchmark object" },
|
|
2429
|
+
{ "StartBenchmark", (PyCFunction) StartBenchmark, METH_VARARGS, "Start a new benchmark with some options" },
|
|
2430
|
+
{ "EndBenchmark", (PyCFunction) EndBenchmark, METH_NOARGS, "End a given benchmark" },
|
|
2431
|
+
{ "GetBenchmark", (PyCFunction) GetBenchmark, METH_VARARGS, "Returns contents of a benchmark object" },
|
|
2432
|
+
{ "GetGeneralBenchmarks", (PyCFunction) GetAllBenchmarks, METH_NOARGS, "Retrieve general benchmark info as a dictionary."},
|
|
2433
|
+
#endif
|
|
2434
|
+
{ "int2Bytes", (PyCFunction) toBytes, METH_O, "convert an integer object to a bytes object."},
|
|
2435
|
+
{ "toInt", (PyCFunction) toInt, METH_O, "convert modular integer into an integer object."},
|
|
2436
|
+
{ "getMod", (PyCFunction) getMod, METH_O, "get the modulus of a given modular integer object."},
|
|
2437
|
+
{ "reduce", (PyCFunction) Integer_reduce, METH_O, "reduce a modular integer by its modulus. x = mod(y)"},
|
|
2438
|
+
{ NULL, NULL }
|
|
2439
|
+
};
|
|
2440
|
+
|
|
2441
|
+
static int int_traverse(PyObject *m, visitproc visit, void *arg) {
|
|
2442
|
+
Py_VISIT(GETSTATE(m)->error);
|
|
2443
|
+
#if defined(BENCHMARK_ENABLED)
|
|
2444
|
+
Py_VISIT(GETSTATE(m)->dBench);
|
|
2445
|
+
#endif
|
|
2446
|
+
return 0;
|
|
2447
|
+
}
|
|
2448
|
+
|
|
2449
|
+
static int int_clear(PyObject *m) {
|
|
2450
|
+
Py_CLEAR(GETSTATE(m)->error);
|
|
2451
|
+
Py_XDECREF(IntegerError);
|
|
2452
|
+
#if defined(BENCHMARK_ENABLED)
|
|
2453
|
+
//printf("int_clear: Refcnt dBench = '%i'\n", (int) Py_REFCNT(GETSTATE(m)->dBench));
|
|
2454
|
+
Py_CLEAR(GETSTATE(m)->dBench);
|
|
2455
|
+
#endif
|
|
2456
|
+
return 0;
|
|
2457
|
+
}
|
|
2458
|
+
|
|
2459
|
+
static int int_free(PyObject *m) {
|
|
2460
|
+
// Defensive cleanup for OpenSSL PRNG to prevent hangs during Python 3.12+ shutdown
|
|
2461
|
+
// Only cleanup if not in abnormal finalization state
|
|
2462
|
+
if(m != NULL && !CHARM_PY_IS_FINALIZING()) {
|
|
2463
|
+
// Note: RAND_cleanup() was removed in OpenSSL 1.1.0
|
|
2464
|
+
// Modern OpenSSL handles cleanup automatically
|
|
2465
|
+
// This is a no-op for compatibility but prevents potential hangs
|
|
2466
|
+
}
|
|
2467
|
+
return 0;
|
|
2468
|
+
}
|
|
2469
|
+
|
|
2470
|
+
static struct PyModuleDef moduledef = {
|
|
2471
|
+
PyModuleDef_HEAD_INIT,
|
|
2472
|
+
"integer",
|
|
2473
|
+
NULL,
|
|
2474
|
+
sizeof(struct module_state),
|
|
2475
|
+
module_methods,
|
|
2476
|
+
NULL,
|
|
2477
|
+
int_traverse,
|
|
2478
|
+
(inquiry) int_clear,
|
|
2479
|
+
(freefunc) int_free
|
|
2480
|
+
};
|
|
2481
|
+
|
|
2482
|
+
#define CLEAN_EXIT goto LEAVE;
|
|
2483
|
+
#define INITERROR return NULL
|
|
2484
|
+
PyMODINIT_FUNC
|
|
2485
|
+
PyInit_integer(void) {
|
|
2486
|
+
PyObject *m=NULL;
|
|
2487
|
+
if (PyType_Ready(&IntegerType) < 0)
|
|
2488
|
+
CLEAN_EXIT;
|
|
2489
|
+
#ifdef BENCHMARK_ENABLED
|
|
2490
|
+
if(import_benchmark() < 0)
|
|
2491
|
+
CLEAN_EXIT;
|
|
2492
|
+
if(PyType_Ready(&BenchmarkType) < 0)
|
|
2493
|
+
INITERROR;
|
|
2494
|
+
#endif
|
|
2495
|
+
|
|
2496
|
+
// initialize module
|
|
2497
|
+
m = PyModule_Create(&moduledef);
|
|
2498
|
+
// add integer type to module
|
|
2499
|
+
struct module_state *st = GETSTATE(m);
|
|
2500
|
+
st->error = PyErr_NewException("integer.Error", NULL, NULL);
|
|
2501
|
+
if (st->error == NULL)
|
|
2502
|
+
CLEAN_EXIT;
|
|
2503
|
+
IntegerError = st->error;
|
|
2504
|
+
#ifdef BENCHMARK_ENABLED
|
|
2505
|
+
st->dBench = NULL;
|
|
2506
|
+
tmpBench = NULL;
|
|
2507
|
+
#endif
|
|
2508
|
+
|
|
2509
|
+
Py_INCREF(&IntegerType);
|
|
2510
|
+
PyModule_AddObject(m, "integer", (PyObject *) &IntegerType);
|
|
2511
|
+
|
|
2512
|
+
#ifdef BENCHMARK_ENABLED
|
|
2513
|
+
// add integer error to module
|
|
2514
|
+
ADD_BENCHMARK_OPTIONS(m);
|
|
2515
|
+
#endif
|
|
2516
|
+
// initialize PRNG
|
|
2517
|
+
// replace with read from some source of randomness
|
|
2518
|
+
#ifndef MS_WINDOWS
|
|
2519
|
+
debug("Linux: seeding openssl prng.\n");
|
|
2520
|
+
char *rand_file = "/dev/urandom";
|
|
2521
|
+
RAND_load_file(rand_file, RAND_MAX_BYTES);
|
|
2522
|
+
#else
|
|
2523
|
+
debug("Windows: seeding openssl prng.\n");
|
|
2524
|
+
RAND_poll();
|
|
2525
|
+
#endif
|
|
2526
|
+
|
|
2527
|
+
LEAVE:
|
|
2528
|
+
if (PyErr_Occurred()) {
|
|
2529
|
+
printf("ERROR: module load failed!\n");
|
|
2530
|
+
PyErr_Clear();
|
|
2531
|
+
if(m!=NULL) {
|
|
2532
|
+
Py_XDECREF(m);
|
|
2533
|
+
}
|
|
2534
|
+
INITERROR;
|
|
2535
|
+
}
|
|
2536
|
+
|
|
2537
|
+
debug("importing integer module.\n");
|
|
2538
|
+
return m;
|
|
2539
|
+
}
|