pq_crypto 0.3.2 → 0.5.0
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.
- checksums.yaml +4 -4
- data/.github/workflows/ci.yml +56 -0
- data/CHANGELOG.md +62 -0
- data/GET_STARTED.md +366 -40
- data/README.md +76 -233
- data/SECURITY.md +107 -82
- data/ext/pqcrypto/extconf.rb +169 -87
- data/ext/pqcrypto/mldsa_api.h +1 -48
- data/ext/pqcrypto/mlkem_api.h +1 -18
- data/ext/pqcrypto/pq_externalmu.c +89 -204
- data/ext/pqcrypto/pqcrypto_native_api.h +129 -0
- data/ext/pqcrypto/pqcrypto_ruby_secure.c +484 -84
- data/ext/pqcrypto/pqcrypto_secure.c +203 -78
- data/ext/pqcrypto/pqcrypto_secure.h +53 -14
- data/ext/pqcrypto/pqcrypto_version.h +7 -0
- data/ext/pqcrypto/randombytes.h +9 -0
- data/ext/pqcrypto/vendor/.vendored +10 -5
- data/ext/pqcrypto/vendor/mldsa-native/BUILDING.md +105 -0
- data/ext/pqcrypto/vendor/mldsa-native/LICENSE +286 -0
- data/ext/pqcrypto/vendor/mldsa-native/META.yml +24 -0
- data/ext/pqcrypto/vendor/mldsa-native/README.md +221 -0
- data/ext/pqcrypto/vendor/mldsa-native/SECURITY.md +8 -0
- data/ext/pqcrypto/vendor/mldsa-native/mldsa/mldsa_native.c +721 -0
- data/ext/pqcrypto/vendor/mldsa-native/mldsa/mldsa_native.h +975 -0
- data/ext/pqcrypto/vendor/mldsa-native/mldsa/mldsa_native_asm.S +724 -0
- data/ext/pqcrypto/vendor/mldsa-native/mldsa/mldsa_native_config.h +723 -0
- data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/cbmc.h +166 -0
- data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/common.h +321 -0
- data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/ct.c +21 -0
- data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/ct.h +385 -0
- data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/debug.c +73 -0
- data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/debug.h +130 -0
- data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/fips202/fips202.c +277 -0
- data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/fips202/fips202.h +244 -0
- data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/fips202/fips202x4.c +182 -0
- data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/fips202/fips202x4.h +117 -0
- data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/fips202/keccakf1600.c +438 -0
- data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/fips202/keccakf1600.h +105 -0
- data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/fips202/native/aarch64/auto.h +71 -0
- data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/fips202/native/aarch64/src/fips202_native_aarch64.h +62 -0
- data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/fips202/native/aarch64/src/keccak_f1600_x1_scalar_asm.S +376 -0
- data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/fips202/native/aarch64/src/keccak_f1600_x1_v84a_asm.S +204 -0
- data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/fips202/native/aarch64/src/keccak_f1600_x2_v84a_asm.S +259 -0
- data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/fips202/native/aarch64/src/keccak_f1600_x4_v8a_scalar_hybrid_asm.S +1077 -0
- data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/fips202/native/aarch64/src/keccak_f1600_x4_v8a_v84a_scalar_hybrid_asm.S +987 -0
- data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/fips202/native/aarch64/src/keccakf1600_round_constants.c +41 -0
- data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/fips202/native/aarch64/x1_scalar.h +26 -0
- data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/fips202/native/aarch64/x1_v84a.h +35 -0
- data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/fips202/native/aarch64/x2_v84a.h +37 -0
- data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/fips202/native/aarch64/x4_v8a_scalar.h +27 -0
- data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/fips202/native/aarch64/x4_v8a_v84a_scalar.h +36 -0
- data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/fips202/native/api.h +69 -0
- data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/fips202/native/armv81m/README.md +10 -0
- data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/fips202/native/armv81m/mve.h +32 -0
- data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/fips202/native/armv81m/src/fips202_native_armv81m.h +20 -0
- data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/fips202/native/armv81m/src/keccak_f1600_x4_mve.S +638 -0
- data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/fips202/native/armv81m/src/keccak_f1600_x4_mve.c +136 -0
- data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/fips202/native/armv81m/src/keccakf1600_round_constants.c +52 -0
- data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/fips202/native/auto.h +29 -0
- data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/fips202/native/x86_64/src/KeccakP_1600_times4_SIMD256.c +488 -0
- data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/fips202/native/x86_64/src/KeccakP_1600_times4_SIMD256.h +16 -0
- data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/fips202/native/x86_64/xkcp.h +31 -0
- data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/native/aarch64/meta.h +247 -0
- data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/native/aarch64/src/aarch64_zetas.c +231 -0
- data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/native/aarch64/src/arith_native_aarch64.h +150 -0
- data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/native/aarch64/src/intt.S +753 -0
- data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/native/aarch64/src/mld_polyvecl_pointwise_acc_montgomery_l4.S +129 -0
- data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/native/aarch64/src/mld_polyvecl_pointwise_acc_montgomery_l5.S +145 -0
- data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/native/aarch64/src/mld_polyvecl_pointwise_acc_montgomery_l7.S +177 -0
- data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/native/aarch64/src/ntt.S +653 -0
- data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/native/aarch64/src/pointwise_montgomery.S +79 -0
- data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/native/aarch64/src/poly_caddq_asm.S +53 -0
- data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/native/aarch64/src/poly_chknorm_asm.S +55 -0
- data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/native/aarch64/src/poly_decompose_32_asm.S +85 -0
- data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/native/aarch64/src/poly_decompose_88_asm.S +85 -0
- data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/native/aarch64/src/poly_use_hint_32_asm.S +102 -0
- data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/native/aarch64/src/poly_use_hint_88_asm.S +110 -0
- data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/native/aarch64/src/polyz_unpack_17_asm.S +72 -0
- data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/native/aarch64/src/polyz_unpack_19_asm.S +69 -0
- data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/native/aarch64/src/polyz_unpack_table.c +40 -0
- data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/native/aarch64/src/rej_uniform_asm.S +189 -0
- data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/native/aarch64/src/rej_uniform_eta2_asm.S +135 -0
- data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/native/aarch64/src/rej_uniform_eta4_asm.S +128 -0
- data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/native/aarch64/src/rej_uniform_eta_table.c +543 -0
- data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/native/aarch64/src/rej_uniform_table.c +62 -0
- data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/native/api.h +649 -0
- data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/native/meta.h +23 -0
- data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/native/x86_64/meta.h +315 -0
- data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/native/x86_64/src/arith_native_x86_64.h +124 -0
- data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/native/x86_64/src/consts.c +157 -0
- data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/native/x86_64/src/consts.h +27 -0
- data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/native/x86_64/src/intt.S +2311 -0
- data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/native/x86_64/src/ntt.S +2383 -0
- data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/native/x86_64/src/nttunpack.S +239 -0
- data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/native/x86_64/src/pointwise.S +131 -0
- data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/native/x86_64/src/pointwise_acc_l4.S +139 -0
- data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/native/x86_64/src/pointwise_acc_l5.S +155 -0
- data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/native/x86_64/src/pointwise_acc_l7.S +187 -0
- data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/native/x86_64/src/poly_caddq_avx2.c +61 -0
- data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/native/x86_64/src/poly_chknorm_avx2.c +52 -0
- data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/native/x86_64/src/poly_decompose_32_avx2.c +155 -0
- data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/native/x86_64/src/poly_decompose_88_avx2.c +155 -0
- data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/native/x86_64/src/poly_use_hint_32_avx2.c +102 -0
- data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/native/x86_64/src/poly_use_hint_88_avx2.c +104 -0
- data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/native/x86_64/src/polyz_unpack_17_avx2.c +91 -0
- data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/native/x86_64/src/polyz_unpack_19_avx2.c +93 -0
- data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/native/x86_64/src/rej_uniform_avx2.c +126 -0
- data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/native/x86_64/src/rej_uniform_eta2_avx2.c +155 -0
- data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/native/x86_64/src/rej_uniform_eta4_avx2.c +139 -0
- data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/native/x86_64/src/rej_uniform_table.c +160 -0
- data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/packing.c +293 -0
- data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/packing.h +224 -0
- data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/params.h +77 -0
- data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/poly.c +991 -0
- data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/poly.h +393 -0
- data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/poly_kl.c +946 -0
- data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/poly_kl.h +360 -0
- data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/polyvec.c +877 -0
- data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/polyvec.h +725 -0
- data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/randombytes.h +26 -0
- data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/reduce.h +139 -0
- data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/rounding.h +249 -0
- data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/sign.c +1511 -0
- data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/sign.h +806 -0
- data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/symmetric.h +68 -0
- data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/sys.h +268 -0
- data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/zetas.inc +55 -0
- data/ext/pqcrypto/vendor/mlkem-native/BUILDING.md +104 -0
- data/ext/pqcrypto/vendor/mlkem-native/LICENSE +294 -0
- data/ext/pqcrypto/vendor/mlkem-native/META.yml +30 -0
- data/ext/pqcrypto/vendor/mlkem-native/README.md +223 -0
- data/ext/pqcrypto/vendor/mlkem-native/RELEASE.md +86 -0
- data/ext/pqcrypto/vendor/mlkem-native/SECURITY.md +8 -0
- data/ext/pqcrypto/vendor/mlkem-native/mlkem/README.md +23 -0
- data/ext/pqcrypto/vendor/mlkem-native/mlkem/mlkem_native.c +660 -0
- data/ext/pqcrypto/vendor/mlkem-native/mlkem/mlkem_native.h +538 -0
- data/ext/pqcrypto/vendor/mlkem-native/mlkem/mlkem_native_asm.S +681 -0
- data/ext/pqcrypto/vendor/mlkem-native/mlkem/mlkem_native_config.h +709 -0
- data/ext/pqcrypto/vendor/mlkem-native/mlkem/src/cbmc.h +174 -0
- data/ext/pqcrypto/vendor/mlkem-native/mlkem/src/common.h +274 -0
- data/ext/pqcrypto/vendor/mlkem-native/mlkem/src/compress.c +717 -0
- data/ext/pqcrypto/vendor/mlkem-native/mlkem/src/compress.h +688 -0
- data/ext/pqcrypto/vendor/mlkem-native/mlkem/src/debug.c +64 -0
- data/ext/pqcrypto/vendor/mlkem-native/mlkem/src/debug.h +128 -0
- data/ext/pqcrypto/vendor/mlkem-native/mlkem/src/fips202/fips202.c +251 -0
- data/ext/pqcrypto/vendor/mlkem-native/mlkem/src/fips202/fips202.h +158 -0
- data/ext/pqcrypto/vendor/mlkem-native/mlkem/src/fips202/fips202x4.c +208 -0
- data/ext/pqcrypto/vendor/mlkem-native/mlkem/src/fips202/fips202x4.h +80 -0
- data/ext/pqcrypto/vendor/mlkem-native/mlkem/src/fips202/keccakf1600.c +463 -0
- data/ext/pqcrypto/vendor/mlkem-native/mlkem/src/fips202/keccakf1600.h +98 -0
- data/ext/pqcrypto/vendor/mlkem-native/mlkem/src/fips202/native/aarch64/auto.h +70 -0
- data/ext/pqcrypto/vendor/mlkem-native/mlkem/src/fips202/native/aarch64/src/fips202_native_aarch64.h +69 -0
- data/ext/pqcrypto/vendor/mlkem-native/mlkem/src/fips202/native/aarch64/src/keccak_f1600_x1_scalar_asm.S +375 -0
- data/ext/pqcrypto/vendor/mlkem-native/mlkem/src/fips202/native/aarch64/src/keccak_f1600_x1_v84a_asm.S +203 -0
- data/ext/pqcrypto/vendor/mlkem-native/mlkem/src/fips202/native/aarch64/src/keccak_f1600_x2_v84a_asm.S +258 -0
- data/ext/pqcrypto/vendor/mlkem-native/mlkem/src/fips202/native/aarch64/src/keccak_f1600_x4_v8a_scalar_hybrid_asm.S +1076 -0
- data/ext/pqcrypto/vendor/mlkem-native/mlkem/src/fips202/native/aarch64/src/keccak_f1600_x4_v8a_v84a_scalar_hybrid_asm.S +986 -0
- data/ext/pqcrypto/vendor/mlkem-native/mlkem/src/fips202/native/aarch64/src/keccakf1600_round_constants.c +46 -0
- data/ext/pqcrypto/vendor/mlkem-native/mlkem/src/fips202/native/aarch64/x1_scalar.h +25 -0
- data/ext/pqcrypto/vendor/mlkem-native/mlkem/src/fips202/native/aarch64/x1_v84a.h +34 -0
- data/ext/pqcrypto/vendor/mlkem-native/mlkem/src/fips202/native/aarch64/x2_v84a.h +35 -0
- data/ext/pqcrypto/vendor/mlkem-native/mlkem/src/fips202/native/aarch64/x4_v8a_scalar.h +26 -0
- data/ext/pqcrypto/vendor/mlkem-native/mlkem/src/fips202/native/aarch64/x4_v8a_v84a_scalar.h +35 -0
- data/ext/pqcrypto/vendor/mlkem-native/mlkem/src/fips202/native/api.h +117 -0
- data/ext/pqcrypto/vendor/mlkem-native/mlkem/src/fips202/native/armv81m/README.md +10 -0
- data/ext/pqcrypto/vendor/mlkem-native/mlkem/src/fips202/native/armv81m/mve.h +79 -0
- data/ext/pqcrypto/vendor/mlkem-native/mlkem/src/fips202/native/armv81m/src/fips202_native_armv81m.h +35 -0
- data/ext/pqcrypto/vendor/mlkem-native/mlkem/src/fips202/native/armv81m/src/keccak_f1600_x4_mve.S +667 -0
- data/ext/pqcrypto/vendor/mlkem-native/mlkem/src/fips202/native/armv81m/src/keccak_f1600_x4_mve.c +40 -0
- data/ext/pqcrypto/vendor/mlkem-native/mlkem/src/fips202/native/armv81m/src/keccakf1600_round_constants.c +51 -0
- data/ext/pqcrypto/vendor/mlkem-native/mlkem/src/fips202/native/armv81m/src/state_extract_bytes_x4_mve.S +290 -0
- data/ext/pqcrypto/vendor/mlkem-native/mlkem/src/fips202/native/armv81m/src/state_xor_bytes_x4_mve.S +314 -0
- data/ext/pqcrypto/vendor/mlkem-native/mlkem/src/fips202/native/auto.h +28 -0
- data/ext/pqcrypto/vendor/mlkem-native/mlkem/src/fips202/native/x86_64/keccak_f1600_x4_avx2.h +33 -0
- data/ext/pqcrypto/vendor/mlkem-native/mlkem/src/fips202/native/x86_64/src/fips202_native_x86_64.h +41 -0
- data/ext/pqcrypto/vendor/mlkem-native/mlkem/src/fips202/native/x86_64/src/keccak_f1600_x4_avx2.S +451 -0
- data/ext/pqcrypto/vendor/mlkem-native/mlkem/src/fips202/native/x86_64/src/keccakf1600_constants.c +51 -0
- data/ext/pqcrypto/vendor/mlkem-native/mlkem/src/indcpa.c +622 -0
- data/ext/pqcrypto/vendor/mlkem-native/mlkem/src/indcpa.h +156 -0
- data/ext/pqcrypto/vendor/mlkem-native/mlkem/src/kem.c +446 -0
- data/ext/pqcrypto/vendor/mlkem-native/mlkem/src/kem.h +326 -0
- data/ext/pqcrypto/vendor/mlkem-native/mlkem/src/native/aarch64/README.md +16 -0
- data/ext/pqcrypto/vendor/mlkem-native/mlkem/src/native/aarch64/meta.h +122 -0
- data/ext/pqcrypto/vendor/mlkem-native/mlkem/src/native/aarch64/src/aarch64_zetas.c +174 -0
- data/ext/pqcrypto/vendor/mlkem-native/mlkem/src/native/aarch64/src/arith_native_aarch64.h +177 -0
- data/ext/pqcrypto/vendor/mlkem-native/mlkem/src/native/aarch64/src/intt.S +628 -0
- data/ext/pqcrypto/vendor/mlkem-native/mlkem/src/native/aarch64/src/ntt.S +562 -0
- data/ext/pqcrypto/vendor/mlkem-native/mlkem/src/native/aarch64/src/poly_mulcache_compute_asm.S +127 -0
- data/ext/pqcrypto/vendor/mlkem-native/mlkem/src/native/aarch64/src/poly_reduce_asm.S +150 -0
- data/ext/pqcrypto/vendor/mlkem-native/mlkem/src/native/aarch64/src/poly_tobytes_asm.S +117 -0
- data/ext/pqcrypto/vendor/mlkem-native/mlkem/src/native/aarch64/src/poly_tomont_asm.S +98 -0
- data/ext/pqcrypto/vendor/mlkem-native/mlkem/src/native/aarch64/src/polyvec_basemul_acc_montgomery_cached_asm_k2.S +261 -0
- data/ext/pqcrypto/vendor/mlkem-native/mlkem/src/native/aarch64/src/polyvec_basemul_acc_montgomery_cached_asm_k3.S +314 -0
- data/ext/pqcrypto/vendor/mlkem-native/mlkem/src/native/aarch64/src/polyvec_basemul_acc_montgomery_cached_asm_k4.S +368 -0
- data/ext/pqcrypto/vendor/mlkem-native/mlkem/src/native/aarch64/src/rej_uniform_asm.S +226 -0
- data/ext/pqcrypto/vendor/mlkem-native/mlkem/src/native/aarch64/src/rej_uniform_table.c +542 -0
- data/ext/pqcrypto/vendor/mlkem-native/mlkem/src/native/api.h +637 -0
- data/ext/pqcrypto/vendor/mlkem-native/mlkem/src/native/meta.h +25 -0
- data/ext/pqcrypto/vendor/mlkem-native/mlkem/src/native/riscv64/README.md +11 -0
- data/ext/pqcrypto/vendor/mlkem-native/mlkem/src/native/riscv64/meta.h +128 -0
- data/ext/pqcrypto/vendor/mlkem-native/mlkem/src/native/riscv64/src/arith_native_riscv64.h +45 -0
- data/ext/pqcrypto/vendor/mlkem-native/mlkem/src/native/riscv64/src/rv64v_debug.c +81 -0
- data/ext/pqcrypto/vendor/mlkem-native/mlkem/src/native/riscv64/src/rv64v_debug.h +145 -0
- data/ext/pqcrypto/vendor/mlkem-native/mlkem/src/native/riscv64/src/rv64v_izetas.inc +27 -0
- data/ext/pqcrypto/vendor/mlkem-native/mlkem/src/native/riscv64/src/rv64v_poly.c +805 -0
- data/ext/pqcrypto/vendor/mlkem-native/mlkem/src/native/riscv64/src/rv64v_zetas.inc +27 -0
- data/ext/pqcrypto/vendor/mlkem-native/mlkem/src/native/riscv64/src/rv64v_zetas_basemul.inc +39 -0
- data/ext/pqcrypto/vendor/mlkem-native/mlkem/src/native/x86_64/README.md +4 -0
- data/ext/pqcrypto/vendor/mlkem-native/mlkem/src/native/x86_64/meta.h +304 -0
- data/ext/pqcrypto/vendor/mlkem-native/mlkem/src/native/x86_64/src/arith_native_x86_64.h +309 -0
- data/ext/pqcrypto/vendor/mlkem-native/mlkem/src/native/x86_64/src/compress_consts.c +94 -0
- data/ext/pqcrypto/vendor/mlkem-native/mlkem/src/native/x86_64/src/compress_consts.h +45 -0
- data/ext/pqcrypto/vendor/mlkem-native/mlkem/src/native/x86_64/src/consts.c +102 -0
- data/ext/pqcrypto/vendor/mlkem-native/mlkem/src/native/x86_64/src/consts.h +25 -0
- data/ext/pqcrypto/vendor/mlkem-native/mlkem/src/native/x86_64/src/intt.S +719 -0
- data/ext/pqcrypto/vendor/mlkem-native/mlkem/src/native/x86_64/src/mulcache_compute.S +90 -0
- data/ext/pqcrypto/vendor/mlkem-native/mlkem/src/native/x86_64/src/ntt.S +639 -0
- data/ext/pqcrypto/vendor/mlkem-native/mlkem/src/native/x86_64/src/nttfrombytes.S +193 -0
- data/ext/pqcrypto/vendor/mlkem-native/mlkem/src/native/x86_64/src/ntttobytes.S +181 -0
- data/ext/pqcrypto/vendor/mlkem-native/mlkem/src/native/x86_64/src/nttunpack.S +174 -0
- data/ext/pqcrypto/vendor/mlkem-native/mlkem/src/native/x86_64/src/poly_compress_d10.S +382 -0
- data/ext/pqcrypto/vendor/mlkem-native/mlkem/src/native/x86_64/src/poly_compress_d11.S +448 -0
- data/ext/pqcrypto/vendor/mlkem-native/mlkem/src/native/x86_64/src/poly_compress_d4.S +163 -0
- data/ext/pqcrypto/vendor/mlkem-native/mlkem/src/native/x86_64/src/poly_compress_d5.S +220 -0
- data/ext/pqcrypto/vendor/mlkem-native/mlkem/src/native/x86_64/src/poly_decompress_d10.S +228 -0
- data/ext/pqcrypto/vendor/mlkem-native/mlkem/src/native/x86_64/src/poly_decompress_d11.S +277 -0
- data/ext/pqcrypto/vendor/mlkem-native/mlkem/src/native/x86_64/src/poly_decompress_d4.S +180 -0
- data/ext/pqcrypto/vendor/mlkem-native/mlkem/src/native/x86_64/src/poly_decompress_d5.S +192 -0
- data/ext/pqcrypto/vendor/mlkem-native/mlkem/src/native/x86_64/src/polyvec_basemul_acc_montgomery_cached_asm_k2.S +502 -0
- data/ext/pqcrypto/vendor/mlkem-native/mlkem/src/native/x86_64/src/polyvec_basemul_acc_montgomery_cached_asm_k3.S +750 -0
- data/ext/pqcrypto/vendor/mlkem-native/mlkem/src/native/x86_64/src/polyvec_basemul_acc_montgomery_cached_asm_k4.S +998 -0
- data/ext/pqcrypto/vendor/mlkem-native/mlkem/src/native/x86_64/src/reduce.S +218 -0
- data/ext/pqcrypto/vendor/mlkem-native/mlkem/src/native/x86_64/src/rej_uniform_asm.S +103 -0
- data/ext/pqcrypto/vendor/mlkem-native/mlkem/src/native/x86_64/src/rej_uniform_table.c +544 -0
- data/ext/pqcrypto/vendor/mlkem-native/mlkem/src/native/x86_64/src/tomont.S +155 -0
- data/ext/pqcrypto/vendor/mlkem-native/mlkem/src/params.h +76 -0
- data/ext/pqcrypto/vendor/mlkem-native/mlkem/src/poly.c +572 -0
- data/ext/pqcrypto/vendor/mlkem-native/mlkem/src/poly.h +317 -0
- data/ext/pqcrypto/vendor/mlkem-native/mlkem/src/poly_k.c +502 -0
- data/ext/pqcrypto/vendor/mlkem-native/mlkem/src/poly_k.h +668 -0
- data/ext/pqcrypto/vendor/mlkem-native/mlkem/src/randombytes.h +60 -0
- data/ext/pqcrypto/vendor/mlkem-native/mlkem/src/sampling.c +362 -0
- data/ext/pqcrypto/vendor/mlkem-native/mlkem/src/sampling.h +118 -0
- data/ext/pqcrypto/vendor/mlkem-native/mlkem/src/symmetric.h +70 -0
- data/ext/pqcrypto/vendor/mlkem-native/mlkem/src/sys.h +260 -0
- data/ext/pqcrypto/vendor/mlkem-native/mlkem/src/verify.c +20 -0
- data/ext/pqcrypto/vendor/mlkem-native/mlkem/src/verify.h +464 -0
- data/ext/pqcrypto/vendor/mlkem-native/mlkem/src/zetas.inc +30 -0
- data/lib/pq_crypto/algorithm_registry.rb +200 -0
- data/lib/pq_crypto/hybrid_kem.rb +1 -12
- data/lib/pq_crypto/kem.rb +104 -13
- data/lib/pq_crypto/pkcs8.rb +387 -0
- data/lib/pq_crypto/serialization.rb +1 -14
- data/lib/pq_crypto/signature.rb +123 -17
- data/lib/pq_crypto/spki.rb +131 -0
- data/lib/pq_crypto/version.rb +1 -1
- data/lib/pq_crypto.rb +79 -20
- data/script/vendor_libs.rb +88 -155
- metadata +241 -73
- data/ext/pqcrypto/vendor/pqclean/common/aes.c +0 -639
- data/ext/pqcrypto/vendor/pqclean/common/aes.h +0 -64
- data/ext/pqcrypto/vendor/pqclean/common/compat.h +0 -73
- data/ext/pqcrypto/vendor/pqclean/common/crypto_declassify.h +0 -7
- data/ext/pqcrypto/vendor/pqclean/common/fips202.c +0 -928
- data/ext/pqcrypto/vendor/pqclean/common/fips202.h +0 -166
- data/ext/pqcrypto/vendor/pqclean/common/keccak2x/feat.S +0 -168
- data/ext/pqcrypto/vendor/pqclean/common/keccak2x/fips202x2.c +0 -684
- data/ext/pqcrypto/vendor/pqclean/common/keccak2x/fips202x2.h +0 -60
- data/ext/pqcrypto/vendor/pqclean/common/keccak4x/KeccakP-1600-times4-SIMD256.c +0 -1028
- data/ext/pqcrypto/vendor/pqclean/common/keccak4x/KeccakP-1600-times4-SnP.h +0 -50
- data/ext/pqcrypto/vendor/pqclean/common/keccak4x/KeccakP-1600-unrolling.macros +0 -198
- data/ext/pqcrypto/vendor/pqclean/common/keccak4x/Makefile +0 -8
- data/ext/pqcrypto/vendor/pqclean/common/keccak4x/Makefile.Microsoft_nmake +0 -8
- data/ext/pqcrypto/vendor/pqclean/common/keccak4x/SIMD256-config.h +0 -3
- data/ext/pqcrypto/vendor/pqclean/common/keccak4x/align.h +0 -34
- data/ext/pqcrypto/vendor/pqclean/common/keccak4x/brg_endian.h +0 -142
- data/ext/pqcrypto/vendor/pqclean/common/nistseedexpander.c +0 -101
- data/ext/pqcrypto/vendor/pqclean/common/nistseedexpander.h +0 -39
- data/ext/pqcrypto/vendor/pqclean/common/randombytes.c +0 -355
- data/ext/pqcrypto/vendor/pqclean/common/randombytes.h +0 -27
- data/ext/pqcrypto/vendor/pqclean/common/sha2.c +0 -769
- data/ext/pqcrypto/vendor/pqclean/common/sha2.h +0 -173
- data/ext/pqcrypto/vendor/pqclean/common/sp800-185.c +0 -156
- data/ext/pqcrypto/vendor/pqclean/common/sp800-185.h +0 -27
- data/ext/pqcrypto/vendor/pqclean/crypto_kem/ml-kem-768/clean/LICENSE +0 -5
- data/ext/pqcrypto/vendor/pqclean/crypto_kem/ml-kem-768/clean/Makefile +0 -19
- data/ext/pqcrypto/vendor/pqclean/crypto_kem/ml-kem-768/clean/Makefile.Microsoft_nmake +0 -23
- data/ext/pqcrypto/vendor/pqclean/crypto_kem/ml-kem-768/clean/api.h +0 -18
- data/ext/pqcrypto/vendor/pqclean/crypto_kem/ml-kem-768/clean/cbd.c +0 -83
- data/ext/pqcrypto/vendor/pqclean/crypto_kem/ml-kem-768/clean/cbd.h +0 -11
- data/ext/pqcrypto/vendor/pqclean/crypto_kem/ml-kem-768/clean/indcpa.c +0 -327
- data/ext/pqcrypto/vendor/pqclean/crypto_kem/ml-kem-768/clean/indcpa.h +0 -22
- data/ext/pqcrypto/vendor/pqclean/crypto_kem/ml-kem-768/clean/kem.c +0 -164
- data/ext/pqcrypto/vendor/pqclean/crypto_kem/ml-kem-768/clean/kem.h +0 -23
- data/ext/pqcrypto/vendor/pqclean/crypto_kem/ml-kem-768/clean/ntt.c +0 -146
- data/ext/pqcrypto/vendor/pqclean/crypto_kem/ml-kem-768/clean/ntt.h +0 -14
- data/ext/pqcrypto/vendor/pqclean/crypto_kem/ml-kem-768/clean/params.h +0 -36
- data/ext/pqcrypto/vendor/pqclean/crypto_kem/ml-kem-768/clean/poly.c +0 -299
- data/ext/pqcrypto/vendor/pqclean/crypto_kem/ml-kem-768/clean/poly.h +0 -37
- data/ext/pqcrypto/vendor/pqclean/crypto_kem/ml-kem-768/clean/polyvec.c +0 -188
- data/ext/pqcrypto/vendor/pqclean/crypto_kem/ml-kem-768/clean/polyvec.h +0 -26
- data/ext/pqcrypto/vendor/pqclean/crypto_kem/ml-kem-768/clean/reduce.c +0 -41
- data/ext/pqcrypto/vendor/pqclean/crypto_kem/ml-kem-768/clean/reduce.h +0 -13
- data/ext/pqcrypto/vendor/pqclean/crypto_kem/ml-kem-768/clean/symmetric-shake.c +0 -71
- data/ext/pqcrypto/vendor/pqclean/crypto_kem/ml-kem-768/clean/symmetric.h +0 -30
- data/ext/pqcrypto/vendor/pqclean/crypto_kem/ml-kem-768/clean/verify.c +0 -67
- data/ext/pqcrypto/vendor/pqclean/crypto_kem/ml-kem-768/clean/verify.h +0 -13
- data/ext/pqcrypto/vendor/pqclean/crypto_sign/ml-dsa-65/clean/LICENSE +0 -5
- data/ext/pqcrypto/vendor/pqclean/crypto_sign/ml-dsa-65/clean/Makefile +0 -19
- data/ext/pqcrypto/vendor/pqclean/crypto_sign/ml-dsa-65/clean/Makefile.Microsoft_nmake +0 -23
- data/ext/pqcrypto/vendor/pqclean/crypto_sign/ml-dsa-65/clean/api.h +0 -50
- data/ext/pqcrypto/vendor/pqclean/crypto_sign/ml-dsa-65/clean/ntt.c +0 -98
- data/ext/pqcrypto/vendor/pqclean/crypto_sign/ml-dsa-65/clean/ntt.h +0 -10
- data/ext/pqcrypto/vendor/pqclean/crypto_sign/ml-dsa-65/clean/packing.c +0 -261
- data/ext/pqcrypto/vendor/pqclean/crypto_sign/ml-dsa-65/clean/packing.h +0 -31
- data/ext/pqcrypto/vendor/pqclean/crypto_sign/ml-dsa-65/clean/params.h +0 -44
- data/ext/pqcrypto/vendor/pqclean/crypto_sign/ml-dsa-65/clean/poly.c +0 -799
- data/ext/pqcrypto/vendor/pqclean/crypto_sign/ml-dsa-65/clean/poly.h +0 -52
- data/ext/pqcrypto/vendor/pqclean/crypto_sign/ml-dsa-65/clean/polyvec.c +0 -415
- data/ext/pqcrypto/vendor/pqclean/crypto_sign/ml-dsa-65/clean/polyvec.h +0 -65
- data/ext/pqcrypto/vendor/pqclean/crypto_sign/ml-dsa-65/clean/reduce.c +0 -69
- data/ext/pqcrypto/vendor/pqclean/crypto_sign/ml-dsa-65/clean/reduce.h +0 -17
- data/ext/pqcrypto/vendor/pqclean/crypto_sign/ml-dsa-65/clean/rounding.c +0 -92
- data/ext/pqcrypto/vendor/pqclean/crypto_sign/ml-dsa-65/clean/rounding.h +0 -14
- data/ext/pqcrypto/vendor/pqclean/crypto_sign/ml-dsa-65/clean/sign.c +0 -407
- data/ext/pqcrypto/vendor/pqclean/crypto_sign/ml-dsa-65/clean/sign.h +0 -47
- data/ext/pqcrypto/vendor/pqclean/crypto_sign/ml-dsa-65/clean/symmetric-shake.c +0 -26
- data/ext/pqcrypto/vendor/pqclean/crypto_sign/ml-dsa-65/clean/symmetric.h +0 -34
data/lib/pq_crypto/signature.rb
CHANGED
|
@@ -6,22 +6,33 @@ module PQCrypto
|
|
|
6
6
|
module Signature
|
|
7
7
|
CANONICAL_ALGORITHM = :ml_dsa_65
|
|
8
8
|
|
|
9
|
-
DETAILS =
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
9
|
+
DETAILS = AlgorithmRegistry.details_for_family(:ml_dsa).freeze
|
|
10
|
+
|
|
11
|
+
NATIVE_DISPATCH = {
|
|
12
|
+
ml_dsa_44: {
|
|
13
|
+
keypair: :native_ml_dsa_44_keypair,
|
|
14
|
+
sign: :native_ml_dsa_44_sign,
|
|
15
|
+
verify: :native_ml_dsa_44_verify,
|
|
16
|
+
keypair_from_seed: :native_ml_dsa_44_keypair_from_seed,
|
|
17
|
+
}.freeze,
|
|
18
|
+
ml_dsa_65: {
|
|
19
|
+
keypair: :native_sign_keypair,
|
|
20
|
+
sign: :native_sign,
|
|
21
|
+
verify: :native_verify,
|
|
22
|
+
keypair_from_seed: :native_ml_dsa_keypair_from_seed,
|
|
23
|
+
}.freeze,
|
|
24
|
+
ml_dsa_87: {
|
|
25
|
+
keypair: :native_ml_dsa_87_keypair,
|
|
26
|
+
sign: :native_ml_dsa_87_sign,
|
|
27
|
+
verify: :native_ml_dsa_87_verify,
|
|
28
|
+
keypair_from_seed: :native_ml_dsa_87_keypair_from_seed,
|
|
18
29
|
}.freeze,
|
|
19
30
|
}.freeze
|
|
20
31
|
|
|
21
32
|
class << self
|
|
22
33
|
def generate(algorithm = CANONICAL_ALGORITHM)
|
|
23
|
-
resolve_algorithm!(algorithm)
|
|
24
|
-
public_key, secret_key = PQCrypto.__send__(:
|
|
34
|
+
algorithm = resolve_algorithm!(algorithm)
|
|
35
|
+
public_key, secret_key = PQCrypto.__send__(native_method_for(algorithm, :keypair))
|
|
25
36
|
Keypair.new(PublicKey.new(algorithm, public_key), SecretKey.new(algorithm, secret_key))
|
|
26
37
|
end
|
|
27
38
|
|
|
@@ -59,6 +70,26 @@ module PQCrypto
|
|
|
59
70
|
SecretKey.new(resolved_algorithm, bytes)
|
|
60
71
|
end
|
|
61
72
|
|
|
73
|
+
def public_key_from_spki_der(der, algorithm: nil)
|
|
74
|
+
resolved_algorithm, bytes = SPKI.decode_der(der)
|
|
75
|
+
validate_algorithm_match!(algorithm, resolved_algorithm) if algorithm
|
|
76
|
+
PublicKey.new(resolve_algorithm!(resolved_algorithm), bytes)
|
|
77
|
+
end
|
|
78
|
+
|
|
79
|
+
def public_key_from_spki_pem(pem, algorithm: nil)
|
|
80
|
+
resolved_algorithm, bytes = SPKI.decode_pem(pem)
|
|
81
|
+
validate_algorithm_match!(algorithm, resolved_algorithm) if algorithm
|
|
82
|
+
PublicKey.new(resolve_algorithm!(resolved_algorithm), bytes)
|
|
83
|
+
end
|
|
84
|
+
|
|
85
|
+
def secret_key_from_pkcs8_der(der)
|
|
86
|
+
secret_key_from_decoded_pkcs8(*PKCS8.decode_der(der))
|
|
87
|
+
end
|
|
88
|
+
|
|
89
|
+
def secret_key_from_pkcs8_pem(pem)
|
|
90
|
+
secret_key_from_decoded_pkcs8(*PKCS8.decode_pem(pem))
|
|
91
|
+
end
|
|
92
|
+
|
|
62
93
|
def details(algorithm)
|
|
63
94
|
DETAILS.fetch(resolve_algorithm!(algorithm)).dup
|
|
64
95
|
end
|
|
@@ -75,9 +106,43 @@ module PQCrypto
|
|
|
75
106
|
raise UnsupportedAlgorithmError, "Unsupported signature algorithm: #{algorithm.inspect}"
|
|
76
107
|
end
|
|
77
108
|
|
|
109
|
+
def secret_key_from_decoded_pkcs8(algorithm, format, material)
|
|
110
|
+
algorithm = resolve_algorithm!(algorithm)
|
|
111
|
+
|
|
112
|
+
case format
|
|
113
|
+
when :expanded
|
|
114
|
+
SecretKey.new(algorithm, material)
|
|
115
|
+
when :seed
|
|
116
|
+
_public_key, expanded = PQCrypto.__send__(native_method_for(algorithm, :keypair_from_seed), material)
|
|
117
|
+
SecretKey.new(algorithm, expanded)
|
|
118
|
+
when :both
|
|
119
|
+
_seed, expanded = material
|
|
120
|
+
SecretKey.new(algorithm, expanded)
|
|
121
|
+
else
|
|
122
|
+
raise SerializationError, "Unsupported ML-DSA PKCS#8 private key format: #{format.inspect}"
|
|
123
|
+
end
|
|
124
|
+
rescue ArgumentError => e
|
|
125
|
+
raise InvalidKeyError, e.message
|
|
126
|
+
end
|
|
127
|
+
|
|
128
|
+
def native_method_for(algorithm, operation)
|
|
129
|
+
NATIVE_DISPATCH.fetch(resolve_algorithm!(algorithm)).fetch(operation)
|
|
130
|
+
end
|
|
131
|
+
|
|
132
|
+
def validate_algorithm_match!(expected_algorithm, actual_algorithm)
|
|
133
|
+
expected = resolve_algorithm!(expected_algorithm)
|
|
134
|
+
return if expected == actual_algorithm
|
|
135
|
+
|
|
136
|
+
raise SerializationError,
|
|
137
|
+
"Expected #{expected.inspect}, got #{actual_algorithm.inspect} (SPKI key algorithm mismatch)"
|
|
138
|
+
rescue UnsupportedAlgorithmError => e
|
|
139
|
+
raise SerializationError, e.message
|
|
140
|
+
end
|
|
141
|
+
|
|
78
142
|
def _streaming_sign(secret_key, io, chunk_size, context)
|
|
143
|
+
validate_streaming_algorithm!(secret_key.algorithm)
|
|
79
144
|
validate_chunk_size!(chunk_size)
|
|
80
|
-
validate_context!(context)
|
|
145
|
+
context = validate_context!(context)
|
|
81
146
|
validate_io!(io)
|
|
82
147
|
|
|
83
148
|
sk_bytes = secret_key.__send__(:bytes_for_native)
|
|
@@ -87,7 +152,7 @@ module PQCrypto
|
|
|
87
152
|
raise InvalidKeyError, e.message
|
|
88
153
|
end
|
|
89
154
|
|
|
90
|
-
builder = PQCrypto.__send__(:_native_mldsa_mu_builder_new, tr, context
|
|
155
|
+
builder = PQCrypto.__send__(:_native_mldsa_mu_builder_new, tr, context)
|
|
91
156
|
builder_consumed = false
|
|
92
157
|
mu = nil
|
|
93
158
|
begin
|
|
@@ -103,8 +168,9 @@ module PQCrypto
|
|
|
103
168
|
end
|
|
104
169
|
|
|
105
170
|
def _streaming_verify(public_key, io, signature, chunk_size, context)
|
|
171
|
+
validate_streaming_algorithm!(public_key.algorithm)
|
|
106
172
|
validate_chunk_size!(chunk_size)
|
|
107
|
-
validate_context!(context)
|
|
173
|
+
context = validate_context!(context)
|
|
108
174
|
validate_io!(io)
|
|
109
175
|
|
|
110
176
|
pk_bytes = public_key.__send__(:bytes_for_native)
|
|
@@ -114,7 +180,7 @@ module PQCrypto
|
|
|
114
180
|
raise InvalidKeyError, e.message
|
|
115
181
|
end
|
|
116
182
|
|
|
117
|
-
builder = PQCrypto.__send__(:_native_mldsa_mu_builder_new, tr, context
|
|
183
|
+
builder = PQCrypto.__send__(:_native_mldsa_mu_builder_new, tr, context)
|
|
118
184
|
builder_consumed = false
|
|
119
185
|
mu = nil
|
|
120
186
|
sig_bytes = String(signature).b
|
|
@@ -162,6 +228,14 @@ module PQCrypto
|
|
|
162
228
|
if ctx.bytesize > 255
|
|
163
229
|
raise ArgumentError, "context must be at most 255 bytes (FIPS 204)"
|
|
164
230
|
end
|
|
231
|
+
ctx
|
|
232
|
+
end
|
|
233
|
+
|
|
234
|
+
def validate_streaming_algorithm!(algorithm)
|
|
235
|
+
return if resolve_algorithm!(algorithm) == CANONICAL_ALGORITHM
|
|
236
|
+
|
|
237
|
+
raise UnsupportedAlgorithmError,
|
|
238
|
+
"Streaming sign_io/verify_io currently supports only #{CANONICAL_ALGORITHM.inspect}"
|
|
165
239
|
end
|
|
166
240
|
end
|
|
167
241
|
|
|
@@ -203,8 +277,16 @@ module PQCrypto
|
|
|
203
277
|
Serialization.public_key_to_pqc_container_pem(@algorithm, @bytes)
|
|
204
278
|
end
|
|
205
279
|
|
|
280
|
+
def to_spki_der
|
|
281
|
+
SPKI.encode_der(@algorithm, @bytes)
|
|
282
|
+
end
|
|
283
|
+
|
|
284
|
+
def to_spki_pem
|
|
285
|
+
SPKI.encode_pem(@algorithm, @bytes)
|
|
286
|
+
end
|
|
287
|
+
|
|
206
288
|
def verify(message, signature)
|
|
207
|
-
PQCrypto.__send__(:
|
|
289
|
+
PQCrypto.__send__(Signature.send(:native_method_for, @algorithm, :verify), String(message).b, String(signature).b, @bytes)
|
|
208
290
|
rescue ArgumentError => e
|
|
209
291
|
raise InvalidKeyError, e.message
|
|
210
292
|
end
|
|
@@ -273,8 +355,32 @@ module PQCrypto
|
|
|
273
355
|
Serialization.secret_key_to_pqc_container_pem(@algorithm, @bytes)
|
|
274
356
|
end
|
|
275
357
|
|
|
358
|
+
def to_pkcs8_der(format: :expanded)
|
|
359
|
+
case format
|
|
360
|
+
when :expanded
|
|
361
|
+
PKCS8.encode_der(@algorithm, @bytes, format: :expanded)
|
|
362
|
+
when :seed, :both
|
|
363
|
+
raise SerializationError,
|
|
364
|
+
"ML-DSA seed/both PKCS#8 export requires original seed material; use PQCrypto::PKCS8.encode_der/encode_pem directly"
|
|
365
|
+
else
|
|
366
|
+
raise SerializationError, "Unsupported PKCS#8 private key format: #{format.inspect}"
|
|
367
|
+
end
|
|
368
|
+
end
|
|
369
|
+
|
|
370
|
+
def to_pkcs8_pem(format: :expanded)
|
|
371
|
+
case format
|
|
372
|
+
when :expanded
|
|
373
|
+
PKCS8.encode_pem(@algorithm, @bytes, format: :expanded)
|
|
374
|
+
when :seed, :both
|
|
375
|
+
raise SerializationError,
|
|
376
|
+
"ML-DSA seed/both PKCS#8 export requires original seed material; use PQCrypto::PKCS8.encode_der/encode_pem directly"
|
|
377
|
+
else
|
|
378
|
+
raise SerializationError, "Unsupported PKCS#8 private key format: #{format.inspect}"
|
|
379
|
+
end
|
|
380
|
+
end
|
|
381
|
+
|
|
276
382
|
def sign(message)
|
|
277
|
-
PQCrypto.__send__(:
|
|
383
|
+
PQCrypto.__send__(Signature.send(:native_method_for, @algorithm, :sign), String(message).b, @bytes)
|
|
278
384
|
rescue ArgumentError => e
|
|
279
385
|
raise InvalidKeyError, e.message
|
|
280
386
|
end
|
|
@@ -0,0 +1,131 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "openssl"
|
|
4
|
+
|
|
5
|
+
module PQCrypto
|
|
6
|
+
module SPKI
|
|
7
|
+
PEM_LABEL = "PUBLIC KEY"
|
|
8
|
+
PEM_BEGIN = "-----BEGIN #{PEM_LABEL}-----"
|
|
9
|
+
PEM_END = "-----END #{PEM_LABEL}-----"
|
|
10
|
+
|
|
11
|
+
class << self
|
|
12
|
+
def encode_der(algorithm_symbol, public_key_bytes)
|
|
13
|
+
entry = AlgorithmRegistry.fetch(algorithm_symbol)
|
|
14
|
+
validate_public_key_algorithm!(algorithm_symbol, entry)
|
|
15
|
+
|
|
16
|
+
bytes = String(public_key_bytes).b
|
|
17
|
+
expected = entry.fetch(:public_key_bytes)
|
|
18
|
+
unless bytes.bytesize == expected
|
|
19
|
+
raise SerializationError,
|
|
20
|
+
"Invalid #{algorithm_symbol.inspect} public key length: expected #{expected}, got #{bytes.bytesize}"
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
OpenSSL::ASN1::Sequence.new([
|
|
24
|
+
OpenSSL::ASN1::Sequence.new([
|
|
25
|
+
OpenSSL::ASN1::ObjectId.new(AlgorithmRegistry.standard_oid(algorithm_symbol)),
|
|
26
|
+
]),
|
|
27
|
+
OpenSSL::ASN1::BitString.new(bytes),
|
|
28
|
+
]).to_der.b
|
|
29
|
+
rescue OpenSSL::ASN1::ASN1Error => e
|
|
30
|
+
raise SerializationError, e.message
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
def encode_pem(algorithm_symbol, public_key_bytes)
|
|
34
|
+
der = encode_der(algorithm_symbol, public_key_bytes)
|
|
35
|
+
body = encode_base64(der).scan(/.{1,64}/).join("\n")
|
|
36
|
+
"#{PEM_BEGIN}\n#{body}\n#{PEM_END}\n"
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
def decode_der(der)
|
|
40
|
+
input = String(der).b
|
|
41
|
+
outer = decode_asn1(input)
|
|
42
|
+
raise SerializationError, "SPKI DER contains trailing data" unless outer.to_der.b == input
|
|
43
|
+
raise SerializationError, "SPKI must be an ASN.1 SEQUENCE" unless outer.is_a?(OpenSSL::ASN1::Sequence)
|
|
44
|
+
raise SerializationError, "SPKI SEQUENCE must contain exactly 2 elements" unless outer.value.size == 2
|
|
45
|
+
|
|
46
|
+
algorithm_identifier, subject_public_key = outer.value
|
|
47
|
+
algorithm = decode_algorithm_identifier(algorithm_identifier)
|
|
48
|
+
entry = AlgorithmRegistry.fetch(algorithm)
|
|
49
|
+
validate_public_key_algorithm!(algorithm, entry)
|
|
50
|
+
|
|
51
|
+
unless subject_public_key.is_a?(OpenSSL::ASN1::BitString)
|
|
52
|
+
raise SerializationError, "SPKI subjectPublicKey must be a BIT STRING"
|
|
53
|
+
end
|
|
54
|
+
unless subject_public_key.unused_bits.zero?
|
|
55
|
+
raise SerializationError, "SPKI subjectPublicKey must have zero unused bits"
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
bytes = String(subject_public_key.value).b
|
|
59
|
+
expected = entry.fetch(:public_key_bytes)
|
|
60
|
+
unless bytes.bytesize == expected
|
|
61
|
+
raise SerializationError,
|
|
62
|
+
"Invalid #{algorithm.inspect} SPKI public key length: expected #{expected}, got #{bytes.bytesize}"
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
[algorithm, bytes]
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
def decode_pem(pem)
|
|
69
|
+
der = der_from_pem(pem)
|
|
70
|
+
decode_der(der)
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
private
|
|
74
|
+
|
|
75
|
+
def decode_asn1(der)
|
|
76
|
+
OpenSSL::ASN1.decode(der)
|
|
77
|
+
rescue OpenSSL::ASN1::ASN1Error => e
|
|
78
|
+
raise SerializationError, e.message
|
|
79
|
+
end
|
|
80
|
+
|
|
81
|
+
def decode_algorithm_identifier(value)
|
|
82
|
+
unless value.is_a?(OpenSSL::ASN1::Sequence)
|
|
83
|
+
raise SerializationError, "SPKI algorithm must be an AlgorithmIdentifier SEQUENCE"
|
|
84
|
+
end
|
|
85
|
+
unless value.value.size == 1
|
|
86
|
+
raise SerializationError, "SPKI AlgorithmIdentifier parameters must be absent"
|
|
87
|
+
end
|
|
88
|
+
|
|
89
|
+
oid = value.value.first
|
|
90
|
+
raise SerializationError, "SPKI AlgorithmIdentifier must contain an OBJECT IDENTIFIER" unless oid.is_a?(OpenSSL::ASN1::ObjectId)
|
|
91
|
+
|
|
92
|
+
algorithm = AlgorithmRegistry.by_standard_oid(oid.oid)
|
|
93
|
+
raise SerializationError, "Unsupported SPKI algorithm OID: #{oid.oid}" if algorithm.nil?
|
|
94
|
+
|
|
95
|
+
algorithm
|
|
96
|
+
end
|
|
97
|
+
|
|
98
|
+
def validate_public_key_algorithm!(algorithm_symbol, entry)
|
|
99
|
+
return if %i[ml_kem ml_dsa].include?(entry.fetch(:family))
|
|
100
|
+
|
|
101
|
+
raise SerializationError, "SPKI public key codec is not supported for #{algorithm_symbol.inspect}"
|
|
102
|
+
end
|
|
103
|
+
|
|
104
|
+
def encode_base64(bytes)
|
|
105
|
+
[String(bytes).b].pack("m0")
|
|
106
|
+
end
|
|
107
|
+
|
|
108
|
+
def decode_base64(body)
|
|
109
|
+
compact = body.gsub(/[\r\n]/, "")
|
|
110
|
+
unless compact.match?(/\A(?:[A-Za-z0-9+\/]{4})*(?:[A-Za-z0-9+\/]{2}==|[A-Za-z0-9+\/]{3}=)?\z/)
|
|
111
|
+
raise SerializationError, "Invalid SPKI PEM: invalid base64"
|
|
112
|
+
end
|
|
113
|
+
|
|
114
|
+
compact.unpack1("m0").b
|
|
115
|
+
rescue ArgumentError => e
|
|
116
|
+
raise SerializationError, e.message
|
|
117
|
+
end
|
|
118
|
+
|
|
119
|
+
def der_from_pem(pem)
|
|
120
|
+
text = String(pem)
|
|
121
|
+
match = text.match(/\A#{Regexp.escape(PEM_BEGIN)}\r?\n(?<body>[A-Za-z0-9+\/=\r\n]+)\r?\n#{Regexp.escape(PEM_END)}[ \t\r\n]*\z/)
|
|
122
|
+
raise SerializationError, "Invalid SPKI PEM: expected #{PEM_LABEL.inspect} label" unless match
|
|
123
|
+
|
|
124
|
+
body = match[:body]
|
|
125
|
+
raise SerializationError, "Invalid SPKI PEM: embedded NUL in body" if body.include?("\0")
|
|
126
|
+
|
|
127
|
+
decode_base64(body)
|
|
128
|
+
end
|
|
129
|
+
end
|
|
130
|
+
end
|
|
131
|
+
end
|
data/lib/pq_crypto/version.rb
CHANGED
data/lib/pq_crypto.rb
CHANGED
|
@@ -1,12 +1,10 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
-
require "rbconfig"
|
|
4
|
-
require_relative "pq_crypto/version"
|
|
5
|
-
require_relative "pq_crypto/errors"
|
|
6
|
-
|
|
7
3
|
begin
|
|
8
|
-
require "pqcrypto/pqcrypto_secure"
|
|
4
|
+
require "pqcrypto/pqcrypto_secure" # native extension first
|
|
9
5
|
rescue LoadError => original_error
|
|
6
|
+
require "rbconfig"
|
|
7
|
+
|
|
10
8
|
ext_dir = File.expand_path("pqcrypto", __dir__)
|
|
11
9
|
extensions = [".#{RbConfig::CONFIG.fetch('DLEXT')}", ".bundle", ".so"].uniq
|
|
12
10
|
search_dirs = [ext_dir, File.join(ext_dir, "pqcrypto")].uniq
|
|
@@ -30,13 +28,21 @@ rescue LoadError => original_error
|
|
|
30
28
|
raise original_error unless loaded
|
|
31
29
|
end
|
|
32
30
|
|
|
31
|
+
require_relative "pq_crypto/errors"
|
|
32
|
+
require_relative "pq_crypto/version"
|
|
33
|
+
require_relative "pq_crypto/algorithm_registry"
|
|
33
34
|
require_relative "pq_crypto/serialization"
|
|
35
|
+
require_relative "pq_crypto/spki"
|
|
36
|
+
require_relative "pq_crypto/pkcs8"
|
|
37
|
+
require_relative "pq_crypto/kem"
|
|
38
|
+
require_relative "pq_crypto/signature"
|
|
39
|
+
require_relative "pq_crypto/hybrid_kem"
|
|
34
40
|
|
|
35
41
|
module PQCrypto
|
|
36
42
|
SUITES = {
|
|
37
|
-
kem:
|
|
38
|
-
hybrid_kem:
|
|
39
|
-
signature:
|
|
43
|
+
kem: AlgorithmRegistry.supported_kems,
|
|
44
|
+
hybrid_kem: AlgorithmRegistry.supported_hybrid_kems,
|
|
45
|
+
signature: AlgorithmRegistry.supported_signatures,
|
|
40
46
|
}.freeze
|
|
41
47
|
|
|
42
48
|
NATIVE_EXTENSION_LOADED = true
|
|
@@ -44,14 +50,32 @@ module PQCrypto
|
|
|
44
50
|
module NativeBindings
|
|
45
51
|
NATIVE_METHODS = %i[
|
|
46
52
|
ml_kem_keypair
|
|
53
|
+
ml_kem_keypair_from_seed
|
|
47
54
|
ml_kem_encapsulate
|
|
48
55
|
ml_kem_decapsulate
|
|
56
|
+
ml_kem_512_keypair
|
|
57
|
+
ml_kem_512_keypair_from_seed
|
|
58
|
+
ml_kem_512_encapsulate
|
|
59
|
+
ml_kem_512_decapsulate
|
|
60
|
+
ml_kem_1024_keypair
|
|
61
|
+
ml_kem_1024_keypair_from_seed
|
|
62
|
+
ml_kem_1024_encapsulate
|
|
63
|
+
ml_kem_1024_decapsulate
|
|
49
64
|
hybrid_kem_keypair
|
|
50
65
|
hybrid_kem_encapsulate
|
|
51
66
|
hybrid_kem_decapsulate
|
|
52
67
|
sign_keypair
|
|
53
68
|
sign
|
|
54
69
|
verify
|
|
70
|
+
ml_dsa_44_keypair
|
|
71
|
+
ml_dsa_44_keypair_from_seed
|
|
72
|
+
ml_dsa_keypair_from_seed
|
|
73
|
+
ml_dsa_44_sign
|
|
74
|
+
ml_dsa_44_verify
|
|
75
|
+
ml_dsa_87_keypair
|
|
76
|
+
ml_dsa_87_keypair_from_seed
|
|
77
|
+
ml_dsa_87_sign
|
|
78
|
+
ml_dsa_87_verify
|
|
55
79
|
ct_equals
|
|
56
80
|
secure_wipe
|
|
57
81
|
version
|
|
@@ -65,8 +89,14 @@ module PQCrypto
|
|
|
65
89
|
secret_key_from_pqc_container_pem
|
|
66
90
|
__test_ml_kem_keypair_from_seed
|
|
67
91
|
__test_ml_kem_encapsulate_from_seed
|
|
92
|
+
__test_ml_kem_512_encapsulate_from_seed
|
|
93
|
+
__test_ml_kem_1024_encapsulate_from_seed
|
|
68
94
|
__test_sign_keypair_from_seed
|
|
95
|
+
__test_ml_dsa_44_keypair_from_seed
|
|
96
|
+
__test_ml_dsa_87_keypair_from_seed
|
|
69
97
|
__test_sign_from_seed
|
|
98
|
+
__test_ml_dsa_44_sign_from_seed
|
|
99
|
+
__test_ml_dsa_87_sign_from_seed
|
|
70
100
|
].freeze
|
|
71
101
|
|
|
72
102
|
EXTERNAL_MU_METHODS = %i[
|
|
@@ -99,7 +129,7 @@ module PQCrypto
|
|
|
99
129
|
end
|
|
100
130
|
|
|
101
131
|
def backend
|
|
102
|
-
:
|
|
132
|
+
:native_pq_code_package
|
|
103
133
|
end
|
|
104
134
|
|
|
105
135
|
def native_extension_loaded?
|
|
@@ -127,32 +157,61 @@ module PQCrypto
|
|
|
127
157
|
end
|
|
128
158
|
|
|
129
159
|
module Testing
|
|
130
|
-
|
|
131
|
-
|
|
160
|
+
KEM_KEYPAIR_METHODS = {
|
|
161
|
+
ml_kem_512: :native_ml_kem_512_keypair_from_seed,
|
|
162
|
+
ml_kem_768: :native_ml_kem_keypair_from_seed,
|
|
163
|
+
ml_kem_1024: :native_ml_kem_1024_keypair_from_seed,
|
|
164
|
+
}.freeze
|
|
165
|
+
|
|
166
|
+
KEM_ENCAPSULATE_METHODS = {
|
|
167
|
+
ml_kem_512: :native_test_ml_kem_512_encapsulate_from_seed,
|
|
168
|
+
ml_kem_768: :native_test_ml_kem_encapsulate_from_seed,
|
|
169
|
+
ml_kem_1024: :native_test_ml_kem_1024_encapsulate_from_seed,
|
|
170
|
+
}.freeze
|
|
171
|
+
|
|
172
|
+
MLDSA_KEYPAIR_METHODS = {
|
|
173
|
+
ml_dsa_44: :native_test_ml_dsa_44_keypair_from_seed,
|
|
174
|
+
ml_dsa_65: :native_test_sign_keypair_from_seed,
|
|
175
|
+
ml_dsa_87: :native_test_ml_dsa_87_keypair_from_seed,
|
|
176
|
+
}.freeze
|
|
177
|
+
|
|
178
|
+
MLDSA_SIGN_METHODS = {
|
|
179
|
+
ml_dsa_44: :native_test_ml_dsa_44_sign_from_seed,
|
|
180
|
+
ml_dsa_65: :native_test_sign_from_seed,
|
|
181
|
+
ml_dsa_87: :native_test_ml_dsa_87_sign_from_seed,
|
|
182
|
+
}.freeze
|
|
183
|
+
|
|
184
|
+
def self.ml_kem_keypair_from_seed(seed, algorithm: :ml_kem_768)
|
|
185
|
+
PQCrypto.__send__(KEM_KEYPAIR_METHODS.fetch(algorithm), String(seed).b)
|
|
186
|
+
rescue KeyError
|
|
187
|
+
raise UnsupportedAlgorithmError, "Unsupported ML-KEM KAT algorithm: #{algorithm.inspect}"
|
|
132
188
|
rescue ArgumentError => e
|
|
133
189
|
raise InvalidKeyError, e.message
|
|
134
190
|
end
|
|
135
191
|
|
|
136
|
-
def self.ml_kem_encapsulate_from_seed(public_key, seed)
|
|
137
|
-
PQCrypto.__send__(
|
|
192
|
+
def self.ml_kem_encapsulate_from_seed(public_key, seed, algorithm: :ml_kem_768)
|
|
193
|
+
PQCrypto.__send__(KEM_ENCAPSULATE_METHODS.fetch(algorithm), String(public_key).b, String(seed).b)
|
|
194
|
+
rescue KeyError
|
|
195
|
+
raise UnsupportedAlgorithmError, "Unsupported ML-KEM KAT algorithm: #{algorithm.inspect}"
|
|
138
196
|
rescue ArgumentError => e
|
|
139
197
|
raise InvalidKeyError, e.message
|
|
140
198
|
end
|
|
141
199
|
|
|
142
|
-
def self.ml_dsa_keypair_from_seed(seed)
|
|
143
|
-
PQCrypto.__send__(
|
|
200
|
+
def self.ml_dsa_keypair_from_seed(seed, algorithm: :ml_dsa_65)
|
|
201
|
+
PQCrypto.__send__(MLDSA_KEYPAIR_METHODS.fetch(algorithm), String(seed).b)
|
|
202
|
+
rescue KeyError
|
|
203
|
+
raise UnsupportedAlgorithmError, "Unsupported ML-DSA KAT algorithm: #{algorithm.inspect}"
|
|
144
204
|
rescue ArgumentError => e
|
|
145
205
|
raise InvalidKeyError, e.message
|
|
146
206
|
end
|
|
147
207
|
|
|
148
|
-
def self.ml_dsa_sign_from_seed(message, secret_key, seed)
|
|
149
|
-
PQCrypto.__send__(
|
|
208
|
+
def self.ml_dsa_sign_from_seed(message, secret_key, seed, algorithm: :ml_dsa_65)
|
|
209
|
+
PQCrypto.__send__(MLDSA_SIGN_METHODS.fetch(algorithm), String(message).b, String(secret_key).b, String(seed).b)
|
|
210
|
+
rescue KeyError
|
|
211
|
+
raise UnsupportedAlgorithmError, "Unsupported ML-DSA KAT algorithm: #{algorithm.inspect}"
|
|
150
212
|
rescue ArgumentError => e
|
|
151
213
|
raise InvalidKeyError, e.message
|
|
152
214
|
end
|
|
153
215
|
end
|
|
154
216
|
end
|
|
155
217
|
|
|
156
|
-
require_relative "pq_crypto/kem"
|
|
157
|
-
require_relative "pq_crypto/hybrid_kem"
|
|
158
|
-
require_relative "pq_crypto/signature"
|