Conversation
456e0bc to
d9bca57
Compare
… `...` range in list context
Unblocks jcpan -t OAuth::Lite (was 3/14 test files passing, now 14/14,
197/197 subtests) by providing Java XS implementations for the two
CPAN modules it depends on, plus fixing a Perl-semantics bug in the
list-context range operator.
Crypt::OpenSSL::Random (new CryptOpenSSLRandom.java)
- random_bytes / random_pseudo_bytes -> SecureRandom.nextBytes
- random_seed -> SecureRandom.setSeed
- random_status -> always 1 (SecureRandom is always seeded)
- random_egd -> -1 (unsupported, matches LibreSSL)
Crypt::OpenSSL::RSA (new CryptOpenSSLRSA.java)
- Key parsing: PKCS#1 RSA PRIVATE/PUBLIC KEY and X.509 PUBLIC KEY
via Bouncy Castle PEMParser + JcaPEMKeyConverter
- Sign/verify: java.security.Signature ("<hash>withRSA", PKCS#1 v1.5)
- generate_key via KeyPairGenerator
- get_{public,private}_key_string and get_public_key_x509_string via
BC PemWriter, translating between PKCS#8 and PKCS#1 as needed
- Full set of use_*_hash / use_*_padding selectors; default hash is
SHA-1 to match OAuth 1.0 RSA-SHA1 test vectors; use_pkcs1_padding
is fatal per Crypt::OpenSSL::RSA >= 0.35
- encrypt/decrypt stubbed (not needed for OAuth; croak if called)
Range operator bug:
for (0...6) { ... } looped exactly once with $_ = "" because `...`
was always dispatched to the scalar-context flip-flop emitter. In
real Perl, `...` in list context is identical to `..` (range). Fix:
- EmitBinaryOperatorNode: route both `..` and `...` through
handleRangeOrFlipFlop so scalar context -> flip-flop, list
context -> range
- EmitOperator.handleRangeOperator: always look up the JVM
descriptor under `..` (no separate `...` handler exists, and
none is needed since the scalar flip-flop path still honors
the three-dot variant via node.operator.equals("..."))
Verified: scalar flip-flop with `...` still matches system Perl
(for 1..10 with $_==3...$_==3 still matches 3..10).
Generated with [Devin](https://cli.devin.ai/docs)
Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
…-trips
Builds on the initial Crypt::OpenSSL::{Random,RSA} scaffold to round
out the parts OAuth::Lite's follow-ups suggested.
New: Crypt::OpenSSL::Bignum (CryptOpenSSLBignum.java + Bignum.pm shim)
- Backed by java.math.BigInteger
- Constructors: new_from_bin / _decimal / _hex / _word, zero, one, rand
- Conversions: to_bin (OpenSSL semantics: 0 -> 0 bytes), to_decimal, to_hex
- Arithmetic: add, sub, mul, div (returns ($q,$r)), mod, exp, mod_exp,
mod_inverse, gcd
- Predicates / accessors: equals, cmp, is_zero, is_one, is_odd,
num_bits, num_bytes, copy
- pointer_copy / bless_pointer: marshal the BigInteger across the XS
boundary as a JAVAOBJECT RuntimeScalar (no C pointer semantics needed)
- Crypt::OpenSSL::Bignum::CTX stub (BigInteger is immutable so CTX has
no state to carry)
RSA encrypt / decrypt / private_encrypt / public_decrypt:
- Backed by javax.crypto.Cipher with the transformations
NONE -> RSA/ECB/NoPadding
PKCS1 -> RSA/ECB/PKCS1Padding
PKCS1_OAEP -> RSA/ECB/OAEPWithSHA-1AndMGF1Padding
(PSS is signing-only, SSLv23 unsupported — both croak)
- private_encrypt / public_decrypt plumb through to the same Cipher
transforms; the JCE provider picks the correct PKCS#1 block type
from the (mode, key type) combination.
RSA _new_key_from_parameters / _get_key_parameters:
- Full round-trip wired via Bignum. Accepts any useful subset of
(n, e, d, p, q): derives missing q from n/p (and vice versa),
derives missing d from e and phi(n) when we have both primes,
promotes to a CRT-accelerated RSAPrivateCrtKey whenever possible,
falls back to (n, d) plain private, or stays public-only.
- Rejects bogus "primes" with "OpenSSL error: p not prime" /
"q not prime" so existing CPAN callers can pattern-match on the
text (matches Crypt::OpenSSL::RSA's t/bignum.t expectations).
- _get_key_parameters returns 8 slots (n, e, d, p, q, dmp1, dmq1,
iqmp), undef for anything not known.
Bouncy Castle as the default provider:
- Register BC as a JCE provider (static init) so RIPEMD160withRSA /
WhirlpoolwithRSA / the full PSS family resolve through BC instead
of being NoSuchAlgorithm from SunJCE alone.
- Switch JcaPEMKeyConverter and KeyFactory.getInstance("RSA") to
explicitly use BC so small / non-standard keys (e.g. the 77-bit
canaries in Crypt::OpenSSL::RSA's t/format.t) parse instead of
hitting Sun's "RSA keys must be at least 512 bits" floor.
- sign/verify have a manual PKCS#1 v1.5 DigestInfo fallback for
hashes that lack a bundled <Hash>withRSA Signature service
(notably Whirlpool) — builds the DigestInfo DER with the matching
OID and feeds it through RSA/ECB/PKCS1Padding so the JCE still
applies type-1 padding.
Upstream CPAN test suite results (run against the installed
~/.perlonjava/cpan/build/Crypt-OpenSSL-RSA-0.37-0 tree):
- t/rsa.t 92/92
- t/bignum.t 64/64
- t/sig_die.t 1/1
- t/format.t still fails on a deliberately-broken 77-bit key that
triggers "RSA modulus has a small prime factor" from BC;
acceptable since OpenSSL's own newer validators reject it too
OAuth::Lite end-to-end: 14/14 files, 197/197 subtests (unchanged).
make: green.
Generated with [Devin](https://cli.devin.ai/docs)
Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
dc3d821 to
02869ec
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Investigating
jcpan -t OAuth::Litesurfaced two issues: two missing XS modules (Crypt::OpenSSL::Random,Crypt::OpenSSL::RSA) and a Perl-semantics bug in the list-context...range operator. This PR addresses both.Before: 3/14 test files passing (10 of 14 fail at
use-time with "Can't load loadable object"), 43/197 subtests.After: 14/14 test files, 197/197 subtests.
Changes
New:
Crypt::OpenSSL::Random(CryptOpenSSLRandom.java)Backed by
java.security.SecureRandom:random_bytes/random_pseudo_bytes->SecureRandom.nextBytesrandom_seed->SecureRandom.setSeedrandom_status-> always 1 (JDK SecureRandom is always seeded)random_egd-> -1 (unsupported, matches LibreSSL)New:
Crypt::OpenSSL::RSA(CryptOpenSSLRSA.java)Backed by Bouncy Castle (
bcprov/bcpkix, already on the classpath) +java.security:PEMParser+JcaPEMKeyConverterSignature.getInstance("<hash>withRSA")(PKCS#1 v1.5)generate_keyviaKeyPairGeneratorget_{public,private}_key_string/get_public_key_x509_stringvia BCPemWriter, translating between PKCS#8 and PKCS#1 as neededuse_*_hash/use_*_paddingselectors; default hash is SHA-1 (matches OAuth 1.0 RSA-SHA1 test vectors);use_pkcs1_paddingis fatal per Crypt::OpenSSL::RSA >= 0.35encrypt/decryptstubbed (OAuth doesn't need them; they croak with "not implemented")Bug fix:
...range operator in list contextt/07_signing_requests.texposed thatfor (0...scalar(@$extra)/2-1) { ... }looped exactly once with$_ = ""instead of iterating0..6, because...was being unconditionally dispatched to the scalar-context flip-flop emitter. Real Perl treats...in list context as identical to..(range) —perl -MO=Deparseeven normalizes it.EmitBinaryOperatorNode: route both..and...throughhandleRangeOrFlipFlop, so list context -> range, scalar context -> flip-flopEmitOperator.handleRangeOperator: always look up the JVM descriptor under..(no separate...handler is registered, and none is needed — the scalar flip-flop path still honors the three-dot variant vianode.operator.equals("..."))Scalar flip-flop with
...still matches system Perl (verified1..10with$_==3...$_==3still matches3..10).Test plan
make(unit tests) passesjcpan -t OAuth::Lite-> 14/14 test files, 197/197 subtestsperlvsjperlparity forfor (0...6)and scalar...flip-flop./jperl -e 'use Crypt::OpenSSL::Random; print unpack "H*", Crypt::OpenSSL::Random::random_bytes(10)'Notes / follow-ups (not in this PR)
encrypt/decrypt/private_encrypt/public_decryptare stubbed. Any module that does RSA encryption (rather than signing) will still fail — wire up when needed._new_key_from_parameters/_get_key_parameters(Crypt::OpenSSL::Bignum integration) are not implemented.jcpan -tstill silently continues past its own "Missing dependencies" warning at Makefile.PL time. Orthogonal to this PR.Generated with Devin