pq_crypto 0.5.1 → 0.5.2

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: d5949078149668609462a1e9a3df7b7f767499311b998e4dd651be1d7865ddfc
4
- data.tar.gz: 600fc91b9614aec5f7f61d8c3ab6d11643bbbf919941faf0508384e7ede9dce0
3
+ metadata.gz: 2274795113da1599b664af11b1393a86d68f1886f3536e0a65385b04b8ce03fe
4
+ data.tar.gz: 386fe1093ba0b28a910195a40d7698e0cef91f9f57fc90b3a1aaac3eec4451a5
5
5
  SHA512:
6
- metadata.gz: 2ac70b6f37460e0a56b1601b59ba5660dda7e4c0c87cc03211c9497261b06f632856079622546f6c8b6db6cfff97b1a9355db879958985f48dfe296c5d729b80
7
- data.tar.gz: 9e89256c60b8153518520438b77632eb232660ff88d0b0668cfb8aeea7a50875c2c7297773f3d469952129ccceb6e604e4f619cc4cc2ebbd458fdca9d50e837f
6
+ metadata.gz: f9f73a9d575d9931020e1674f96adafe08816a1f7183b0b948194fcd2fb4da106afb854525ef544409b47bde34c987ac0eae6ce54440b7562f70faf5807446c3
7
+ data.tar.gz: c5e54b45ab8461bd1edd2b3e4e14f0092267232bc3bf1436841488fa7a604fdf66056dfd160767ec2d47b0a4afe37cb660a46a54466677994a3c1d73269959d1
@@ -116,3 +116,50 @@ jobs:
116
116
  echo "OpenSSL 3.5 interop tests must NOT skip on this matrix entry."
117
117
  exit 1
118
118
  fi
119
+
120
+ linux-native-backend:
121
+ needs: test
122
+ name: linux-native-backend
123
+ runs-on: ubuntu-latest
124
+ env:
125
+ PQCRYPTO_NATIVE_ASM: "1"
126
+
127
+ steps:
128
+ - name: Checkout
129
+ uses: actions/checkout@v4
130
+
131
+ - name: Set up Ruby
132
+ uses: ruby/setup-ruby@v1
133
+ with:
134
+ ruby-version: "3.4"
135
+ bundler-cache: true
136
+
137
+ - name: Verify vendored sources
138
+ run: bundle exec rake vendor:verify
139
+
140
+ - name: Compile extension with native x86_64 backend
141
+ run: |
142
+ rm -rf tmp lib/pqcrypto/pqcrypto_secure.so
143
+ bundle exec rake compile
144
+
145
+ - name: Smoke native backend
146
+ run: |
147
+ bundle exec ruby -Ilib -e '
148
+ require "pq_crypto"
149
+
150
+ kem = PQCrypto::KEM.generate(:ml_kem_768)
151
+ enc = kem.public_key.encapsulate
152
+ raise "ML-KEM mismatch" unless kem.secret_key.decapsulate(enc.ciphertext) == enc.shared_secret
153
+
154
+ sig = PQCrypto::Signature.generate(:ml_dsa_65)
155
+ msg = "linux-native-backend".b
156
+ signature = sig.secret_key.sign(msg)
157
+ raise "ML-DSA verify failed" unless sig.public_key.verify(msg, signature)
158
+ '
159
+
160
+ - name: Verify AVX2 native symbols
161
+ run: |
162
+ set -euxo pipefail
163
+ so="lib/pqcrypto/pqcrypto_secure.so"
164
+ test -f "$so"
165
+ nm "$so" | grep -E "pqcr_(mlkem|mldsa).*avx2|keccak.*avx2"
data/CHANGELOG.md CHANGED
@@ -1,5 +1,20 @@
1
1
  # Changelog
2
2
 
3
+ ## [0.5.2] - 2026-05-06
4
+
5
+ ### Build
6
+
7
+ - Added Linux/OpenSSL discovery via `OPENSSL_ROOT_DIR`, `OPENSSL_DIR`, and `pkg-config`.
8
+ - Preserved `$(CFLAGS)`/`$(CCDLFLAGS)` for vendored native objects so Linux shared-object builds keep `-fPIC`.
9
+ - Added opt-in Linux x86_64 native-backend support through `PQCRYPTO_NATIVE_ASM=1`.
10
+ - Added x86_64 AVX2 vendor flags for mlkem-native/mldsa-native when native backends are explicitly enabled.
11
+ - Added separate `PQCRYPTO_NATIVE_ARITH` and `PQCRYPTO_NATIVE_FIPS202` switches for native arithmetic and Keccak/FIPS202 backends.
12
+ - Kept AArch64 native asm enabled by default; verified macOS arm64 still builds ML-KEM/ML-DSA native asm paths.
13
+
14
+ ### CI
15
+
16
+ - Added a Linux native-backend job that compiles with `PQCRYPTO_NATIVE_ASM=1`, runs ML-KEM/ML-DSA smoke checks, and verifies AVX2 symbols in the extension.
17
+
3
18
  ## [0.5.1] - 2026-05-04
4
19
 
5
20
  ### Performance
@@ -39,32 +39,31 @@ if SANITIZE && !SANITIZE.strip.empty?
39
39
  $LDFLAGS << " -fsanitize=#{sanitize}"
40
40
  end
41
41
 
42
- def native_asm_supported_by_default?
43
- host_cpu = RbConfig::CONFIG.fetch("host_cpu", "")
44
- host_os = RbConfig::CONFIG.fetch("host_os", "")
45
- return false if host_os =~ /mswin|mingw|cygwin/i
42
+ def host_cpu
43
+ RbConfig::CONFIG.fetch("host_cpu", "")
44
+ end
46
45
 
47
- host_cpu =~ /\A(?:arm64|aarch64)\z/i
46
+ def host_os
47
+ RbConfig::CONFIG.fetch("host_os", "")
48
48
  end
49
49
 
50
- def parse_native_asm_env(value)
51
- return native_asm_supported_by_default? if value.nil? || value.strip.empty? || value == "auto"
50
+ def aarch64_host?
51
+ host_cpu =~ /\A(?:arm64|aarch64)\z/i
52
+ end
52
53
 
53
- case value.strip.downcase
54
- when "1", "true", "yes", "on", "auto"
55
- true
56
- when "0", "false", "no", "off"
57
- false
58
- else
59
- abort "Invalid PQCRYPTO_NATIVE_ASM=#{value.inspect}; use 1, 0, or auto"
60
- end
54
+ def x86_64_host?
55
+ host_cpu =~ /\A(?:x86_64|amd64|x64)\z/i
61
56
  end
62
57
 
63
- NATIVE_ASM = parse_native_asm_env(ENV["PQCRYPTO_NATIVE_ASM"])
58
+ def native_asm_supported_by_default?
59
+ return false if host_os =~ /mswin|mingw|cygwin/i
64
60
 
65
- def parse_native_backend_env(name)
61
+ aarch64_host?
62
+ end
63
+
64
+ def env_bool(name, default)
66
65
  value = ENV[name]
67
- return NATIVE_ASM if value.nil? || value.strip.empty? || value == "auto"
66
+ return default if value.nil? || value.strip.empty? || value.strip.downcase == "auto"
68
67
 
69
68
  case value.strip.downcase
70
69
  when "1", "true", "yes", "on"
@@ -72,19 +71,53 @@ def parse_native_backend_env(name)
72
71
  when "0", "false", "no", "off"
73
72
  false
74
73
  else
75
- abort "Invalid #{name}=#{value.inspect}; use 1, 0, or auto"
74
+ abort "Invalid #{name}=#{value.inspect}; use 1, 0, true, false, or auto"
76
75
  end
77
76
  end
78
77
 
79
- NATIVE_ARITH = parse_native_backend_env("PQCRYPTO_NATIVE_ARITH")
80
- NATIVE_FIPS202 = parse_native_backend_env("PQCRYPTO_NATIVE_FIPS202")
78
+ NATIVE_ASM = env_bool("PQCRYPTO_NATIVE_ASM", native_asm_supported_by_default?)
79
+ NATIVE_ARITH = env_bool("PQCRYPTO_NATIVE_ARITH", NATIVE_ASM)
80
+ NATIVE_FIPS202 = env_bool("PQCRYPTO_NATIVE_FIPS202", NATIVE_ASM)
81
+
82
+ X86_VENDOR_ARCH_FLAGS = "-mavx2 -mbmi -mbmi2 -mpopcnt -maes -mssse3 -msse4.1 -msse4.2"
83
+
84
+ VENDOR_C_ARCH_FLAGS = +""
85
+ VENDOR_ASM_ARCH_FLAGS = +""
86
+
87
+ if x86_64_host? && (NATIVE_ARITH || NATIVE_FIPS202)
88
+ VENDOR_C_ARCH_FLAGS << "#{X86_VENDOR_ARCH_FLAGS} -fno-tree-vectorize"
89
+ VENDOR_ASM_ARCH_FLAGS << X86_VENDOR_ARCH_FLAGS
90
+ end
91
+
92
+ if ENV["PQCRYPTO_NATIVE_TUNE"] == "1"
93
+ VENDOR_C_ARCH_FLAGS << " -march=native -mtune=native"
94
+ VENDOR_ASM_ARCH_FLAGS << " -march=native -mtune=native"
95
+ end
81
96
 
82
97
  def configure_compiler_environment
83
- return unless RUBY_PLATFORM.include?("darwin")
98
+ if RUBY_PLATFORM.include?("darwin")
99
+ dir_config("homebrew", "/opt/homebrew")
100
+ $CPPFLAGS << " -I/opt/homebrew/include"
101
+ $LDFLAGS << " -L/opt/homebrew/lib"
102
+ return
103
+ end
104
+
105
+ openssl_root = ENV["OPENSSL_ROOT_DIR"] || ENV["OPENSSL_DIR"]
106
+ if openssl_root && !openssl_root.strip.empty? && File.directory?(openssl_root)
107
+ $CPPFLAGS << " -I#{openssl_root}/include"
108
+ %w[lib64 lib].each do |suffix|
109
+ libdir = File.join(openssl_root, suffix)
110
+ next unless File.directory?(libdir)
84
111
 
85
- dir_config("homebrew", "/opt/homebrew")
86
- $CPPFLAGS << " -I/opt/homebrew/include"
87
- $LDFLAGS << " -L/opt/homebrew/lib"
112
+ $LDFLAGS << " -L#{libdir} -Wl,-rpath,#{libdir}"
113
+ break
114
+ end
115
+ elsif find_executable("pkg-config")
116
+ cflags = `pkg-config --cflags openssl 2>/dev/null`.strip
117
+ libs = `pkg-config --libs-only-L openssl 2>/dev/null`.strip
118
+ $CPPFLAGS << " #{cflags}" unless cflags.empty?
119
+ $LDFLAGS << " #{libs}" unless libs.empty?
120
+ end
88
121
  end
89
122
 
90
123
  def native_vendor_sources_for(vendor_dir)
@@ -270,7 +303,7 @@ def inject_native_sources!(config)
270
303
  build_rules << <<~RULE
271
304
  #{object}: #{source}
272
305
  $(ECHO) compiling #{source} [#{kind}-#{level}]
273
- $(Q) $(CC) $(INCFLAGS) $(CPPFLAGS) $(CFLAGS) #{VENDOR_ONLY_CFLAGS} #{flags} $(COUTFLAG)$@ -c $(CSRCFLAG)$<
306
+ $(Q) $(CC) $(INCFLAGS) $(CPPFLAGS) $(CFLAGS) $(CCDLFLAGS) #{VENDOR_ONLY_CFLAGS} #{VENDOR_C_ARCH_FLAGS} #{flags} $(COUTFLAG)$@ -c $(CSRCFLAG)$<
274
307
  RULE
275
308
  end
276
309
 
@@ -291,7 +324,7 @@ def inject_native_sources!(config)
291
324
  build_rules << <<~RULE
292
325
  #{object}: #{source}
293
326
  $(ECHO) assembling #{source} [#{kind}-#{level}]
294
- $(Q) $(CC) $(INCFLAGS) $(CPPFLAGS) $(CFLAGS) #{VENDOR_ONLY_CFLAGS} #{flags} $(COUTFLAG)$@ -c $(CSRCFLAG)$<
327
+ $(Q) $(CC) $(INCFLAGS) $(CPPFLAGS) $(CFLAGS) $(CCDLFLAGS) #{VENDOR_ONLY_CFLAGS} #{VENDOR_ASM_ARCH_FLAGS} #{flags} $(COUTFLAG)$@ -c $(CSRCFLAG)$<
295
328
  RULE
296
329
  end
297
330
  end
@@ -321,9 +354,15 @@ native_config = native_vendor_config(vendor_dir)
321
354
  puts "OpenSSL: system"
322
355
  puts "ML-KEM: mlkem-native vendored"
323
356
  puts "ML-DSA: mldsa-native vendored"
357
+ puts "Host CPU: #{host_cpu} (#{host_os})"
324
358
  puts "Native asm auto/forced: #{NATIVE_ASM ? 'enabled' : 'disabled'}"
325
359
  puts "Native arithmetic backend: #{NATIVE_ARITH ? 'enabled' : 'disabled'}"
326
360
  puts "Native FIPS202 backend: #{NATIVE_FIPS202 ? 'enabled' : 'disabled'}"
361
+ puts "Vendor C arch flags: #{VENDOR_C_ARCH_FLAGS.empty? ? '(none)' : VENDOR_C_ARCH_FLAGS}"
362
+ puts "Vendor ASM arch flags: #{VENDOR_ASM_ARCH_FLAGS.empty? ? '(none)' : VENDOR_ASM_ARCH_FLAGS}"
363
+ if x86_64_host? && (NATIVE_ARITH || NATIVE_FIPS202)
364
+ puts "x86_64 native backend: AVX2 build flags enabled"
365
+ end
327
366
  puts "PQClean fallback: removed"
328
367
  puts "Output: pqcrypto/pqcrypto_secure"
329
368
  puts "===================================="
@@ -2,6 +2,6 @@
2
2
  #ifndef PQCRYPTO_VERSION_H
3
3
  #define PQCRYPTO_VERSION_H
4
4
 
5
- #define PQCRYPTO_VERSION "0.5.1"
5
+ #define PQCRYPTO_VERSION "0.5.2"
6
6
 
7
7
  #endif
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module PQCrypto
4
- VERSION = "0.5.1"
4
+ VERSION = "0.5.2"
5
5
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: pq_crypto
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.5.1
4
+ version: 0.5.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Roman Haydarov