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
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 4f34f4ae9f34414fbbc1f6ffc63de9c24306a6a432138e36442c1e43661fa59e
|
|
4
|
+
data.tar.gz: 6b2a754c55b9a1be4706cf5d835ee08844b54d75d96d43611f22c8c4f68cb10f
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 0b72822b4b645f891e8f87693004f736070b9bba37432a48ffc840ec1a114865ba691db7c1ffc12aab7643369c3883892d9fbcf3c4f7cf895b5938d2ee650b1c
|
|
7
|
+
data.tar.gz: 13c0263600408685f5d484528032305c48e3e3d551799abad990167c9a9d14d0287aabb70fd88dc00f72d6236f15e70c3d9f6e9572ad02276e11674aafd87774
|
data/.github/workflows/ci.yml
CHANGED
|
@@ -35,3 +35,59 @@ jobs:
|
|
|
35
35
|
|
|
36
36
|
- name: Run tests
|
|
37
37
|
run: bundle exec rake test
|
|
38
|
+
|
|
39
|
+
interop-openssl-3-5-required:
|
|
40
|
+
name: interop-openssl-3.5-required
|
|
41
|
+
runs-on: ubuntu-24.04
|
|
42
|
+
|
|
43
|
+
steps:
|
|
44
|
+
- name: Checkout
|
|
45
|
+
uses: actions/checkout@v4
|
|
46
|
+
|
|
47
|
+
- name: Build OpenSSL 3.5
|
|
48
|
+
run: |
|
|
49
|
+
set -euxo pipefail
|
|
50
|
+
sudo apt-get update
|
|
51
|
+
sudo apt-get install -y build-essential perl pkg-config curl ca-certificates
|
|
52
|
+
curl -fsSLO https://www.openssl.org/source/openssl-3.5.0.tar.gz
|
|
53
|
+
tar -xzf openssl-3.5.0.tar.gz
|
|
54
|
+
cd openssl-3.5.0
|
|
55
|
+
./Configure linux-x86_64 --prefix=/opt/openssl-3.5 --openssldir=/opt/openssl-3.5 shared
|
|
56
|
+
make -s -j"$(nproc)"
|
|
57
|
+
sudo make -s install_sw
|
|
58
|
+
echo /opt/openssl-3.5/lib64 | sudo tee /etc/ld.so.conf.d/openssl-3.5.conf
|
|
59
|
+
sudo ldconfig
|
|
60
|
+
/opt/openssl-3.5/bin/openssl version
|
|
61
|
+
/opt/openssl-3.5/bin/openssl version | grep -E '^OpenSSL 3\.(5|[6-9]|[1-9][0-9])\.'
|
|
62
|
+
echo /opt/openssl-3.5/bin >> "$GITHUB_PATH"
|
|
63
|
+
{
|
|
64
|
+
echo "OPENSSL_ROOT_DIR=/opt/openssl-3.5"
|
|
65
|
+
echo "PKG_CONFIG_PATH=/opt/openssl-3.5/lib64/pkgconfig"
|
|
66
|
+
echo "LD_LIBRARY_PATH=/opt/openssl-3.5/lib64"
|
|
67
|
+
} >> "$GITHUB_ENV"
|
|
68
|
+
|
|
69
|
+
- name: Set up Ruby
|
|
70
|
+
uses: ruby/setup-ruby@v1
|
|
71
|
+
with:
|
|
72
|
+
ruby-version: "3.4"
|
|
73
|
+
bundler-cache: true
|
|
74
|
+
|
|
75
|
+
- name: Set up Go
|
|
76
|
+
uses: actions/setup-go@v5
|
|
77
|
+
with:
|
|
78
|
+
go-version: "1.26.0"
|
|
79
|
+
|
|
80
|
+
- name: Compile extension
|
|
81
|
+
run: bundle exec rake compile
|
|
82
|
+
|
|
83
|
+
- name: Run tests
|
|
84
|
+
run: |
|
|
85
|
+
set -o pipefail
|
|
86
|
+
bundle exec rake test 2>&1 | tee rake_test.log
|
|
87
|
+
|
|
88
|
+
- name: Refuse skipped OpenSSL 3.5 interop tests
|
|
89
|
+
run: |
|
|
90
|
+
if grep -E "Skipped: .* (mlkem|mldsa)_spki" rake_test.log; then
|
|
91
|
+
echo "OpenSSL 3.5 interop tests must NOT skip on this matrix entry."
|
|
92
|
+
exit 1
|
|
93
|
+
fi
|
data/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,67 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## [0.5.0] - 2026-05-04
|
|
4
|
+
|
|
5
|
+
### Changed — native backend migration
|
|
6
|
+
|
|
7
|
+
- Replaced the PQClean runtime/build path with PQ Code Package `mlkem-native` and `mldsa-native` as the only ML-KEM / ML-DSA backend.
|
|
8
|
+
- Removed the PQClean fallback entirely so backend failures are attributable to the new native path instead of mixed old/new implementations.
|
|
9
|
+
- Updated the native extension build to require `ext/pqcrypto/vendor/mlkem-native/mlkem/mlkem_native.c` and `ext/pqcrypto/vendor/mldsa-native/mldsa/mldsa_native.c`.
|
|
10
|
+
- Changed vendoring and gem packaging to keep only a minimal PQ Code Package source snapshot, avoiding upstream examples and symlink-heavy trees in packaged gems.
|
|
11
|
+
- Switched native compilation to `-O3`; optional upstream native assembly remains opt-in through `PQCRYPTO_NATIVE_ASM=1`.
|
|
12
|
+
- `PQCrypto.backend` now reports `:native_pq_code_package`.
|
|
13
|
+
|
|
14
|
+
### Fixed
|
|
15
|
+
|
|
16
|
+
- Corrected deterministic ML-DSA test signing on `mldsa-native` by passing the FIPS 204 pure-mode domain-separation prefix (`00 00` for an empty context) into `signature_internal`. This restores deterministic round-trip verification and ML-DSA siggen KAT compatibility.
|
|
17
|
+
|
|
18
|
+
### Documentation
|
|
19
|
+
|
|
20
|
+
- Updated README, GET_STARTED, SECURITY, and migration notes for the native-only backend and the no-PQClean policy.
|
|
21
|
+
- Documented that `pqc_container_*` remains a compatibility serialization format while the cryptographic backend has moved to PQ Code Package native sources.
|
|
22
|
+
|
|
23
|
+
### Migration notes
|
|
24
|
+
|
|
25
|
+
- Source checkouts must refresh vendor sources with `bundle exec rake vendor` before compiling if `ext/pqcrypto/vendor/.vendored` is missing or stale.
|
|
26
|
+
- This release intentionally does not support falling back to PQClean. If native sources are absent or incompatible, the extension build fails early.
|
|
27
|
+
|
|
28
|
+
## [0.4.2] - 2026-04-29
|
|
29
|
+
|
|
30
|
+
### Fixed
|
|
31
|
+
- Fixed native extension build from packaged gem by keeping generated
|
|
32
|
+
`pqcrypto_version.h` available after `make clean`.
|
|
33
|
+
|
|
34
|
+
## [0.4.1] — 2026-04-29
|
|
35
|
+
|
|
36
|
+
### Fixed
|
|
37
|
+
|
|
38
|
+
- Hardened native ML-DSA signing error handling by checking RNG failures.
|
|
39
|
+
- Improved streaming ML-DSA validation and context handling without regressing throughput.
|
|
40
|
+
|
|
41
|
+
## [0.4.0] — 2026-04-28
|
|
42
|
+
|
|
43
|
+
### Added — standard serialization and expanded parameter sets
|
|
44
|
+
|
|
45
|
+
- Added a central algorithm registry with legacy `pqc_container_*` OIDs kept separate from RFC 9935 / RFC 9881 standard OIDs.
|
|
46
|
+
- Added RFC 9935 SPKI public-key and PKCS#8 private-key support for ML-KEM.
|
|
47
|
+
- Added RFC 9881 SPKI public-key and expanded-key PKCS#8 support for ML-DSA.
|
|
48
|
+
- Added public API support for ML-KEM-512, ML-KEM-1024, ML-DSA-44, and ML-DSA-87 alongside the existing ML-KEM-768 and ML-DSA-65 support.
|
|
49
|
+
- Added OpenSSL 3.5+ interoperability tests for standard SPKI / PKCS#8 encodings where supported by the linked OpenSSL.
|
|
50
|
+
- Added NIST ACVP KAT test infrastructure for ML-KEM and ML-DSA parameter sets.
|
|
51
|
+
- Added opt-in ML-DSA seed/both PKCS#8 import support. The default remains off; callers must set `PQCrypto::PKCS8.allow_ml_dsa_seed_format = true`.
|
|
52
|
+
|
|
53
|
+
### Changed
|
|
54
|
+
|
|
55
|
+
- Bumped the gem version to `0.4.0`.
|
|
56
|
+
- `pqc_container_*` remains frozen and project-local. It is still limited to the original three algorithms: `:ml_kem_768`, `:ml_dsa_65`, and `:ml_kem_768_x25519_xwing`.
|
|
57
|
+
- `DETAILS[:oid]` continues to expose the legacy `pqc_container_*` OID for backward compatibility. Standard OIDs are available via `PQCrypto::AlgorithmRegistry.standard_oid`.
|
|
58
|
+
- The native `PQCrypto.version` path now derives from `lib/pq_crypto/version.rb` through a generated C header, avoiding a second manually maintained version string.
|
|
59
|
+
|
|
60
|
+
### Security notes
|
|
61
|
+
|
|
62
|
+
- ML-DSA seed-format imports are opt-in because PQClean does not expose a public ML-DSA derandomized keypair entrypoint. The implementation reuses the thread-local seed-replay path documented in `SECURITY.md`.
|
|
63
|
+
- The project remains unaudited and experimental.
|
|
64
|
+
|
|
3
65
|
## [0.3.2] — 2026-04-25
|
|
4
66
|
|
|
5
67
|
### Added — streaming ML-DSA for large inputs
|
data/GET_STARTED.md
CHANGED
|
@@ -1,98 +1,424 @@
|
|
|
1
1
|
# Getting started with pq_crypto
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
This guide shows the common `pq_crypto` workflows. The README is intentionally
|
|
4
|
+
short; examples and practical details live here.
|
|
5
|
+
|
|
6
|
+
## 1. Install
|
|
7
|
+
|
|
8
|
+
Add the gem to your application:
|
|
9
|
+
|
|
10
|
+
```ruby
|
|
11
|
+
# Gemfile
|
|
12
|
+
gem "pq_crypto"
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
Install it:
|
|
4
16
|
|
|
5
17
|
```bash
|
|
6
18
|
bundle install
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
If you are working from a repository checkout, compile the native extension:
|
|
22
|
+
|
|
23
|
+
```bash
|
|
7
24
|
bundle exec rake compile
|
|
8
25
|
```
|
|
9
26
|
|
|
10
|
-
|
|
27
|
+
Use the gem from Ruby:
|
|
28
|
+
|
|
29
|
+
```ruby
|
|
30
|
+
require "pq_crypto"
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
## 2. Check the available algorithms
|
|
34
|
+
|
|
35
|
+
```ruby
|
|
36
|
+
PQCrypto.supported_kems
|
|
37
|
+
# => [:ml_kem_512, :ml_kem_768, :ml_kem_1024]
|
|
38
|
+
|
|
39
|
+
PQCrypto.supported_signatures
|
|
40
|
+
# => [:ml_dsa_44, :ml_dsa_65, :ml_dsa_87]
|
|
41
|
+
|
|
42
|
+
PQCrypto.supported_hybrid_kems
|
|
43
|
+
# => [:ml_kem_768_x25519_xwing]
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
Useful metadata:
|
|
47
|
+
|
|
48
|
+
```ruby
|
|
49
|
+
PQCrypto.version
|
|
50
|
+
PQCrypto.backend
|
|
51
|
+
|
|
52
|
+
PQCrypto::KEM.details(:ml_kem_768)
|
|
53
|
+
PQCrypto::Signature.details(:ml_dsa_65)
|
|
54
|
+
PQCrypto::AlgorithmRegistry.standard_oid(:ml_kem_768)
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
`DETAILS[:oid]` remains the legacy `pqc_container_*` OID for backward
|
|
58
|
+
compatibility. Use `AlgorithmRegistry.standard_oid` when you need the standard
|
|
59
|
+
RFC OID.
|
|
60
|
+
|
|
61
|
+
## 3. ML-KEM: generate, encapsulate, decapsulate
|
|
62
|
+
|
|
63
|
+
Generate a keypair:
|
|
11
64
|
|
|
12
65
|
```ruby
|
|
13
66
|
keypair = PQCrypto::KEM.generate(:ml_kem_768)
|
|
67
|
+
public_key = keypair.public_key
|
|
68
|
+
secret_key = keypair.secret_key
|
|
14
69
|
```
|
|
15
70
|
|
|
16
|
-
|
|
71
|
+
Encapsulate with the public key:
|
|
17
72
|
|
|
18
73
|
```ruby
|
|
19
|
-
result =
|
|
20
|
-
|
|
74
|
+
result = public_key.encapsulate
|
|
75
|
+
ciphertext = result.ciphertext
|
|
76
|
+
sender_shared_secret = result.shared_secret
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
Decapsulate with the secret key:
|
|
80
|
+
|
|
81
|
+
```ruby
|
|
82
|
+
receiver_shared_secret = secret_key.decapsulate(ciphertext)
|
|
83
|
+
|
|
84
|
+
sender_shared_secret == receiver_shared_secret
|
|
85
|
+
# => true
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
The same API shape applies to other supported ML-KEM parameter sets:
|
|
89
|
+
|
|
90
|
+
```ruby
|
|
91
|
+
PQCrypto::KEM.generate(:ml_kem_512)
|
|
92
|
+
PQCrypto::KEM.generate(:ml_kem_1024)
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
## 4. ML-DSA: sign and verify
|
|
96
|
+
|
|
97
|
+
Generate a signature keypair:
|
|
98
|
+
|
|
99
|
+
```ruby
|
|
100
|
+
keypair = PQCrypto::Signature.generate(:ml_dsa_65)
|
|
101
|
+
public_key = keypair.public_key
|
|
102
|
+
secret_key = keypair.secret_key
|
|
21
103
|
```
|
|
22
104
|
|
|
23
|
-
|
|
105
|
+
Sign and verify a message:
|
|
24
106
|
|
|
25
107
|
```ruby
|
|
26
|
-
|
|
108
|
+
message = "hello".b
|
|
109
|
+
signature = secret_key.sign(message)
|
|
110
|
+
|
|
111
|
+
public_key.verify(message, signature)
|
|
112
|
+
# => true
|
|
113
|
+
|
|
114
|
+
public_key.verify!(message, signature)
|
|
115
|
+
# returns true, or raises on mismatch
|
|
27
116
|
```
|
|
28
117
|
|
|
29
|
-
|
|
118
|
+
The same API shape applies to other supported ML-DSA parameter sets:
|
|
30
119
|
|
|
31
120
|
```ruby
|
|
32
|
-
|
|
121
|
+
PQCrypto::Signature.generate(:ml_dsa_44)
|
|
122
|
+
PQCrypto::Signature.generate(:ml_dsa_87)
|
|
123
|
+
```
|
|
124
|
+
|
|
125
|
+
## 5. ML-DSA for large files
|
|
126
|
+
|
|
127
|
+
For large inputs, use the streaming helpers so the whole message does not need
|
|
128
|
+
to be materialized as one Ruby string.
|
|
129
|
+
|
|
130
|
+
```ruby
|
|
131
|
+
keypair = PQCrypto::Signature.generate(:ml_dsa_65)
|
|
132
|
+
|
|
133
|
+
signature = File.open("document.bin", "rb") do |io|
|
|
134
|
+
keypair.secret_key.sign_io(io, chunk_size: 1 << 20)
|
|
135
|
+
end
|
|
33
136
|
|
|
34
|
-
|
|
35
|
-
|
|
137
|
+
ok = File.open("document.bin", "rb") do |io|
|
|
138
|
+
keypair.public_key.verify_io(io, signature, chunk_size: 1 << 20)
|
|
139
|
+
end
|
|
36
140
|
```
|
|
37
141
|
|
|
38
|
-
|
|
142
|
+
With an optional FIPS 204 context:
|
|
39
143
|
|
|
40
144
|
```ruby
|
|
145
|
+
context = "invoice-v1".b
|
|
146
|
+
|
|
41
147
|
signature = File.open("document.bin", "rb") do |io|
|
|
42
|
-
|
|
148
|
+
keypair.secret_key.sign_io(io, context: context)
|
|
43
149
|
end
|
|
44
150
|
|
|
45
151
|
ok = File.open("document.bin", "rb") do |io|
|
|
46
|
-
|
|
152
|
+
keypair.public_key.verify_io(io, signature, context: context)
|
|
47
153
|
end
|
|
48
154
|
```
|
|
49
155
|
|
|
50
|
-
|
|
156
|
+
Notes:
|
|
157
|
+
|
|
158
|
+
- `context` must match during verification.
|
|
159
|
+
- `context` is limited to 255 bytes by FIPS 204.
|
|
160
|
+
- `chunk_size` must be positive.
|
|
161
|
+
- `sign_io` / `verify_io` are pure ML-DSA streaming helpers. They are not
|
|
162
|
+
HashML-DSA/prehash shortcuts and do not expose public `sign_mu` /
|
|
163
|
+
`verify_mu` APIs.
|
|
164
|
+
|
|
165
|
+
## 6. Hybrid KEM: ML-KEM-768 + X25519 X-Wing
|
|
166
|
+
|
|
167
|
+
```ruby
|
|
168
|
+
keypair = PQCrypto::HybridKEM.generate(:ml_kem_768_x25519_xwing)
|
|
169
|
+
|
|
170
|
+
result = keypair.public_key.encapsulate
|
|
171
|
+
ciphertext = result.ciphertext
|
|
172
|
+
sender_shared_secret = result.shared_secret
|
|
173
|
+
|
|
174
|
+
receiver_shared_secret = keypair.secret_key.decapsulate(ciphertext)
|
|
175
|
+
|
|
176
|
+
sender_shared_secret == receiver_shared_secret
|
|
177
|
+
# => true
|
|
178
|
+
```
|
|
179
|
+
|
|
180
|
+
The raw X-Wing secret key exported by this API is the draft-style 32-byte
|
|
181
|
+
secret seed, not the expanded ML-KEM/X25519 private material.
|
|
182
|
+
|
|
183
|
+
See `SECURITY.md` for audit status and hybrid interoperability caveats.
|
|
184
|
+
|
|
185
|
+
## 7. SPKI public-key serialization
|
|
186
|
+
|
|
187
|
+
Use SPKI when you need standard public-key serialization for ML-KEM or ML-DSA.
|
|
188
|
+
|
|
189
|
+
ML-KEM example:
|
|
190
|
+
|
|
191
|
+
```ruby
|
|
192
|
+
keypair = PQCrypto::KEM.generate(:ml_kem_768)
|
|
193
|
+
|
|
194
|
+
pem = keypair.public_key.to_spki_pem
|
|
195
|
+
imported = PQCrypto::KEM.public_key_from_spki_pem(pem)
|
|
196
|
+
|
|
197
|
+
imported == keypair.public_key
|
|
198
|
+
# => true
|
|
199
|
+
```
|
|
200
|
+
|
|
201
|
+
DER form:
|
|
202
|
+
|
|
203
|
+
```ruby
|
|
204
|
+
der = keypair.public_key.to_spki_der
|
|
205
|
+
imported = PQCrypto::KEM.public_key_from_spki_der(der)
|
|
206
|
+
```
|
|
207
|
+
|
|
208
|
+
ML-DSA example:
|
|
209
|
+
|
|
210
|
+
```ruby
|
|
211
|
+
keypair = PQCrypto::Signature.generate(:ml_dsa_65)
|
|
212
|
+
|
|
213
|
+
pem = keypair.public_key.to_spki_pem
|
|
214
|
+
imported = PQCrypto::Signature.public_key_from_spki_pem(pem)
|
|
215
|
+
```
|
|
216
|
+
|
|
217
|
+
You can require an expected algorithm during import:
|
|
51
218
|
|
|
52
219
|
```ruby
|
|
53
|
-
|
|
54
|
-
signature = File.open("document.bin", "rb") { |io| sig.secret_key.sign_io(io, context: ctx) }
|
|
55
|
-
ok = File.open("document.bin", "rb") { |io| sig.public_key.verify_io(io, signature, context: ctx) }
|
|
220
|
+
PQCrypto::KEM.public_key_from_spki_pem(pem, algorithm: :ml_kem_768)
|
|
56
221
|
```
|
|
57
222
|
|
|
58
|
-
|
|
59
|
-
shortcuts. `verify_io!` raises on mismatch.
|
|
223
|
+
## 8. PKCS#8 private-key serialization
|
|
60
224
|
|
|
61
|
-
|
|
225
|
+
Use PKCS#8 when you need standard private-key serialization for ML-KEM or
|
|
226
|
+
ML-DSA.
|
|
227
|
+
|
|
228
|
+
### ML-KEM PKCS#8
|
|
229
|
+
|
|
230
|
+
`SecretKey#to_pkcs8_pem` exports the expanded private key by default:
|
|
62
231
|
|
|
63
232
|
```ruby
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
233
|
+
keypair = PQCrypto::KEM.generate(:ml_kem_768)
|
|
234
|
+
|
|
235
|
+
pem = keypair.secret_key.to_pkcs8_pem
|
|
236
|
+
imported = PQCrypto::KEM.secret_key_from_pkcs8_pem(pem)
|
|
237
|
+
|
|
238
|
+
imported == keypair.secret_key
|
|
239
|
+
# => true
|
|
67
240
|
```
|
|
68
241
|
|
|
69
|
-
|
|
70
|
-
|
|
242
|
+
DER form:
|
|
243
|
+
|
|
244
|
+
```ruby
|
|
245
|
+
der = keypair.secret_key.to_pkcs8_der
|
|
246
|
+
imported = PQCrypto::KEM.secret_key_from_pkcs8_der(der)
|
|
247
|
+
```
|
|
71
248
|
|
|
72
|
-
|
|
73
|
-
`
|
|
249
|
+
ML-KEM PKCS#8 supports `:seed`, `:expanded`, and `:both` formats. A generated
|
|
250
|
+
`SecretKey` does not retain the original seed, so exporting `:seed` or `:both`
|
|
251
|
+
from `SecretKey#to_pkcs8_*` is intentionally unavailable. If you explicitly
|
|
252
|
+
have the seed material, use the low-level PKCS#8 encoder.
|
|
74
253
|
|
|
75
|
-
|
|
254
|
+
### ML-DSA PKCS#8
|
|
255
|
+
|
|
256
|
+
ML-DSA private keys support expanded-key PKCS#8 by default:
|
|
257
|
+
|
|
258
|
+
```ruby
|
|
259
|
+
keypair = PQCrypto::Signature.generate(:ml_dsa_65)
|
|
260
|
+
|
|
261
|
+
pem = keypair.secret_key.to_pkcs8_pem
|
|
262
|
+
imported = PQCrypto::Signature.secret_key_from_pkcs8_pem(pem)
|
|
263
|
+
```
|
|
264
|
+
|
|
265
|
+
ML-DSA seed/both import is intentionally opt-in:
|
|
76
266
|
|
|
77
267
|
```ruby
|
|
268
|
+
PQCrypto::PKCS8.allow_ml_dsa_seed_format = true
|
|
269
|
+
imported = PQCrypto::Signature.secret_key_from_pkcs8_pem(pem)
|
|
270
|
+
```
|
|
271
|
+
|
|
272
|
+
Seed/both export from an existing ML-DSA `SecretKey` is intentionally not
|
|
273
|
+
available because the object does not retain the original seed material. When
|
|
274
|
+
you explicitly have seed material, call `PQCrypto::PKCS8.encode_der` /
|
|
275
|
+
`encode_pem` directly.
|
|
276
|
+
|
|
277
|
+
## 9. pq_crypto-local container serialization
|
|
278
|
+
|
|
279
|
+
The `pqc_container_*` APIs are retained for backward compatibility with older
|
|
280
|
+
`pq_crypto` releases.
|
|
281
|
+
|
|
282
|
+
```ruby
|
|
283
|
+
keypair = PQCrypto::KEM.generate(:ml_kem_768)
|
|
284
|
+
|
|
78
285
|
der = keypair.public_key.to_pqc_container_der
|
|
79
286
|
imported = PQCrypto::KEM.public_key_from_pqc_container_der(der)
|
|
80
287
|
```
|
|
81
288
|
|
|
82
|
-
|
|
289
|
+
PEM form:
|
|
290
|
+
|
|
291
|
+
```ruby
|
|
292
|
+
pem = keypair.secret_key.to_pqc_container_pem
|
|
293
|
+
imported = PQCrypto::KEM.secret_key_from_pqc_container_pem(pem)
|
|
294
|
+
```
|
|
295
|
+
|
|
296
|
+
Important caveats:
|
|
297
|
+
|
|
298
|
+
- `pqc_container_*` is project-local.
|
|
299
|
+
- It is not ASN.1 SPKI or PKCS#8.
|
|
300
|
+
- It is not advertised as interoperable with external PKI tooling.
|
|
301
|
+
- It remains limited to the original algorithms:
|
|
302
|
+
- `:ml_kem_768`
|
|
303
|
+
- `:ml_dsa_65`
|
|
304
|
+
- `:ml_kem_768_x25519_xwing`
|
|
305
|
+
|
|
306
|
+
For external interoperability, prefer SPKI for public keys and PKCS#8 for
|
|
307
|
+
private keys.
|
|
308
|
+
|
|
309
|
+
## 10. Raw key import/export
|
|
310
|
+
|
|
311
|
+
Raw bytes can be useful when integrating with storage or protocols that already
|
|
312
|
+
handle framing.
|
|
313
|
+
|
|
314
|
+
```ruby
|
|
315
|
+
keypair = PQCrypto::KEM.generate(:ml_kem_768)
|
|
316
|
+
|
|
317
|
+
public_bytes = keypair.public_key.to_bytes
|
|
318
|
+
secret_bytes = keypair.secret_key.to_bytes
|
|
319
|
+
|
|
320
|
+
public_key = PQCrypto::KEM.public_key_from_bytes(:ml_kem_768, public_bytes)
|
|
321
|
+
secret_key = PQCrypto::KEM.secret_key_from_bytes(:ml_kem_768, secret_bytes)
|
|
322
|
+
```
|
|
323
|
+
|
|
324
|
+
Signature keys have the same shape:
|
|
325
|
+
|
|
326
|
+
```ruby
|
|
327
|
+
keypair = PQCrypto::Signature.generate(:ml_dsa_65)
|
|
328
|
+
|
|
329
|
+
public_key = PQCrypto::Signature.public_key_from_bytes(:ml_dsa_65, keypair.public_key.to_bytes)
|
|
330
|
+
secret_key = PQCrypto::Signature.secret_key_from_bytes(:ml_dsa_65, keypair.secret_key.to_bytes)
|
|
331
|
+
```
|
|
332
|
+
|
|
333
|
+
## 11. Secure wiping
|
|
334
|
+
|
|
335
|
+
`PQCrypto.secure_wipe(str)` zeroes a mutable Ruby string in place.
|
|
336
|
+
|
|
337
|
+
```ruby
|
|
338
|
+
raw = File.binread("secret-key.bin")
|
|
339
|
+
key = PQCrypto::KEM.secret_key_from_bytes(:ml_kem_768, raw)
|
|
340
|
+
|
|
341
|
+
PQCrypto.secure_wipe(raw)
|
|
342
|
+
key.wipe!
|
|
343
|
+
```
|
|
344
|
+
|
|
345
|
+
`wipe!` is best-effort only. It clears the current Ruby string buffer owned by
|
|
346
|
+
the key object. It cannot erase every copy that may have been created by Ruby,
|
|
347
|
+
OpenSSL, serialization, logging, or the garbage collector.
|
|
348
|
+
|
|
349
|
+
## 12. Equality and inspection
|
|
83
350
|
|
|
84
|
-
|
|
351
|
+
Key equality uses constant-time comparison through OpenSSL `CRYPTO_memcmp` via
|
|
352
|
+
`PQCrypto.ct_equals`.
|
|
85
353
|
|
|
86
354
|
```ruby
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
PQCrypto.supported_signatures # => [:ml_dsa_65]
|
|
355
|
+
keypair.public_key == imported_public_key
|
|
356
|
+
keypair.secret_key == imported_secret_key
|
|
90
357
|
```
|
|
91
358
|
|
|
92
|
-
|
|
359
|
+
Secret key `inspect` output is intentionally redacted, and secret key objects
|
|
360
|
+
do not expose a public fingerprint method.
|
|
361
|
+
|
|
362
|
+
## 13. Native backend
|
|
363
|
+
|
|
364
|
+
Since `0.5.0`, the build uses PQ Code Package `mlkem-native` / `mldsa-native`
|
|
365
|
+
sources only. There is no PQClean fallback and no separate
|
|
366
|
+
`PQCRYPTO_KECCAK_BACKEND` switch: Keccak/SHAKE comes from the selected PQ Code
|
|
367
|
+
Package native source tree.
|
|
368
|
+
|
|
369
|
+
```bash
|
|
370
|
+
bundle exec rake vendor
|
|
371
|
+
bundle exec rake compile
|
|
372
|
+
```
|
|
373
|
+
|
|
374
|
+
To try the upstream native assembly backend, opt in explicitly:
|
|
375
|
+
|
|
376
|
+
```bash
|
|
377
|
+
PQCRYPTO_NATIVE_ASM=1 bundle exec rake compile
|
|
378
|
+
```
|
|
93
379
|
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
380
|
+
## 14. Async / Fiber scheduler behavior
|
|
381
|
+
|
|
382
|
+
On Ruby 3.4, signing and verification use Ruby's scheduler-aware
|
|
383
|
+
`rb_nogvl(..., RB_NOGVL_OFFLOAD_SAFE)` path automatically. With a scheduler
|
|
384
|
+
that implements `blocking_operation_wait`, blocking native work can be moved
|
|
385
|
+
off the event loop.
|
|
386
|
+
|
|
387
|
+
## 15. Test-only deterministic helpers
|
|
388
|
+
|
|
389
|
+
`PQCrypto::Testing` exposes deterministic helpers for regression tests:
|
|
390
|
+
|
|
391
|
+
```ruby
|
|
392
|
+
PQCrypto::Testing.ml_kem_keypair_from_seed(seed) # 64-byte d||z seed
|
|
393
|
+
PQCrypto::Testing.ml_kem_encapsulate_from_seed(pk, seed) # 32-byte seed
|
|
394
|
+
PQCrypto::Testing.ml_dsa_keypair_from_seed(seed) # 32-byte seed
|
|
395
|
+
PQCrypto::Testing.ml_dsa_sign_from_seed(message, sk, seed)
|
|
396
|
+
```
|
|
397
|
+
|
|
398
|
+
These helpers are intended for tests only. They drive deterministic PQ Code
|
|
399
|
+
Package native entrypoints and are not part of the normal application API.
|
|
400
|
+
|
|
401
|
+
## 16. Development commands
|
|
402
|
+
|
|
403
|
+
Run the test suite:
|
|
404
|
+
|
|
405
|
+
```bash
|
|
406
|
+
bundle exec rake test
|
|
407
|
+
```
|
|
408
|
+
|
|
409
|
+
Refresh the pinned PQ Code Package native vendor snapshot only when intentionally
|
|
410
|
+
updating vendored sources. The vendoring script keeps a minimal, source-gem-safe
|
|
411
|
+
snapshot: `mlkem-native/mlkem`, `mldsa-native/mldsa`, and upstream license/docs
|
|
412
|
+
only. It intentionally omits examples and symlink-heavy upstream trees:
|
|
413
|
+
|
|
414
|
+
```bash
|
|
415
|
+
bundle exec ruby script/vendor_libs.rb
|
|
416
|
+
```
|
|
417
|
+
|
|
418
|
+
To intentionally change the upstream snapshot, override the native package refs:
|
|
419
|
+
|
|
420
|
+
```bash
|
|
421
|
+
MLKEM_NATIVE_REF=<tag-or-commit> \
|
|
422
|
+
MLDSA_NATIVE_REF=<tag-or-commit> \
|
|
423
|
+
bundle exec ruby script/vendor_libs.rb
|
|
424
|
+
```
|