diff --git a/.agents/skills/pr-gate-check/SKILL.md b/.agents/skills/pr-gate-check/SKILL.md index 932b1b4a1f..e5b99c0399 100644 --- a/.agents/skills/pr-gate-check/SKILL.md +++ b/.agents/skills/pr-gate-check/SKILL.md @@ -22,6 +22,8 @@ git rev-list --all --parents | rg ' ( |$)' ``` Pick the merge commit where one parent is `` and the other is the target branch tip at merge time. +If you cannot find it this way, another heuristic is to take the branch name and append `_gate` - that usually has the merge commit we want as tip. + 3. Check builds on that merge commit: ```bash gdev-cli bitbucket get-builds --commit= --all --format=key,state,url diff --git a/CHANGELOG.md b/CHANGELOG.md index 276a85af44..ed4ac50792 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -18,6 +18,7 @@ language runtime. The main focus is on user-observable behavior of the engine. * Added a new `java` backend for the `pyexpat` module that uses a Java XML parser instead of the native `expat` library. It can be useful when running without native access or multiple-context scenarios. This backend is the default when embedding and can be switched back to native `expat` by setting `python.PyExpatModuleBackend` option to `native`. Standalone distribution still defaults to native expat backend. * Add a new context option `python.UnicodeCharacterDatabaseNativeFallback` to control whether the ICU database may fall back to the native unicode character database from CPython for features and characters not supported by ICU. This requires native access to be enabled and is disabled by default for embeddings. * Foreign temporal objects (dates, times, and timezones) are now given a Python class corresponding to their interop traits, i.e., `date`, `time`, `datetime`, or `tzinfo`. This allows any foreign objects with these traits to be used in place of the native Python types and Python methods available on these types work on the foreign types. +* Make BouncyCastle an optional dependency for embedding use cases. BouncyCastle is only needed for legacy RSA, DSA, and EC privat keys versions 0 and 1. To support these from Python embeddings, BouncyCastle must now be explicitly enabled by adding the `org.graalvm.python:python-bouncycastle-support` Maven artifact. ## Version 25.0.1 * Allow users to keep going on unsupported JDK/OS/ARCH combinations at their own risk by opting out of early failure using `-Dtruffle.UseFallbackRuntime=true`, `-Dpolyglot.engine.userResourceCache=/set/to/a/writeable/dir`, `-Dpolyglot.engine.allowUnsupportedPlatform=true`, and `-Dpolyglot.python.UnsupportedPlatformEmulates=[linux|macos|windows]` and `-Dorg.graalvm.python.resources.exclude=native.files`. diff --git a/graalpython/com.oracle.graal.python.bouncycastle/src/META-INF/native-image/org.graalvm.python/python-bouncycastle/native-image.properties b/graalpython/com.oracle.graal.python.bouncycastle/src/META-INF/native-image/org.graalvm.python/python-bouncycastle/native-image.properties new file mode 100644 index 0000000000..13a0ad90d1 --- /dev/null +++ b/graalpython/com.oracle.graal.python.bouncycastle/src/META-INF/native-image/org.graalvm.python/python-bouncycastle/native-image.properties @@ -0,0 +1,2 @@ +# Additional native-image arguments for optional GraalPy BouncyCastle support +Args = --features=com.oracle.graal.python.bouncycastle.BouncyCastleFeature diff --git a/graalpython/com.oracle.graal.python.bouncycastle/src/META-INF/native-image/org.graalvm.python/python-bouncycastle/reflect-config.json b/graalpython/com.oracle.graal.python.bouncycastle/src/META-INF/native-image/org.graalvm.python/python-bouncycastle/reflect-config.json new file mode 100644 index 0000000000..fb104aeb8d --- /dev/null +++ b/graalpython/com.oracle.graal.python.bouncycastle/src/META-INF/native-image/org.graalvm.python/python-bouncycastle/reflect-config.json @@ -0,0 +1,2066 @@ +[ + { + "name": "org.bouncycastle.jcajce.provider.asymmetric.COMPOSITE$Mappings", + "methods": [ + { + "name": "", + "parameterTypes": [] + } + ], + "condition": { + "typeReachable": "org.bouncycastle.jce.provider.BouncyCastleProvider" + } + }, + { + "name": "org.bouncycastle.jcajce.provider.asymmetric.CompositeSignatures$Mappings", + "methods": [ + { + "name": "", + "parameterTypes": [] + } + ], + "condition": { + "typeReachable": "org.bouncycastle.jce.provider.BouncyCastleProvider" + } + }, + { + "name": "org.bouncycastle.jcajce.provider.asymmetric.DH$Mappings", + "methods": [ + { + "name": "", + "parameterTypes": [] + } + ], + "condition": { + "typeReachable": "org.bouncycastle.jce.provider.BouncyCastleProvider" + } + }, + { + "name": "org.bouncycastle.jcajce.provider.asymmetric.DSA$Mappings", + "methods": [ + { + "name": "", + "parameterTypes": [] + } + ], + "condition": { + "typeReachable": "org.bouncycastle.jce.provider.BouncyCastleProvider" + } + }, + { + "name": "org.bouncycastle.jcajce.provider.asymmetric.DSTU4145$Mappings", + "methods": [ + { + "name": "", + "parameterTypes": [] + } + ], + "condition": { + "typeReachable": "org.bouncycastle.jce.provider.BouncyCastleProvider" + } + }, + { + "name": "org.bouncycastle.jcajce.provider.asymmetric.Dilithium$Mappings", + "methods": [ + { + "name": "", + "parameterTypes": [] + } + ], + "condition": { + "typeReachable": "org.bouncycastle.jce.provider.BouncyCastleProvider" + } + }, + { + "name": "org.bouncycastle.jcajce.provider.asymmetric.EC$Mappings", + "methods": [ + { + "name": "", + "parameterTypes": [] + } + ], + "condition": { + "typeReachable": "org.bouncycastle.jce.provider.BouncyCastleProvider" + } + }, + { + "name": "org.bouncycastle.jcajce.provider.asymmetric.ECGOST$Mappings", + "methods": [ + { + "name": "", + "parameterTypes": [] + } + ], + "condition": { + "typeReachable": "org.bouncycastle.jce.provider.BouncyCastleProvider" + } + }, + { + "name": "org.bouncycastle.jcajce.provider.asymmetric.EXTERNAL$Mappings", + "methods": [ + { + "name": "", + "parameterTypes": [] + } + ], + "condition": { + "typeReachable": "org.bouncycastle.jce.provider.BouncyCastleProvider" + } + }, + { + "name": "org.bouncycastle.jcajce.provider.asymmetric.EdEC$Mappings", + "methods": [ + { + "name": "", + "parameterTypes": [] + } + ], + "condition": { + "typeReachable": "org.bouncycastle.jce.provider.BouncyCastleProvider" + } + }, + { + "name": "org.bouncycastle.jcajce.provider.asymmetric.ElGamal$Mappings", + "methods": [ + { + "name": "", + "parameterTypes": [] + } + ], + "condition": { + "typeReachable": "org.bouncycastle.jce.provider.BouncyCastleProvider" + } + }, + { + "name": "org.bouncycastle.jcajce.provider.asymmetric.Falcon$Mappings", + "methods": [ + { + "name": "", + "parameterTypes": [] + } + ], + "condition": { + "typeReachable": "org.bouncycastle.jce.provider.BouncyCastleProvider" + } + }, + { + "name": "org.bouncycastle.jcajce.provider.asymmetric.GM$Mappings", + "methods": [ + { + "name": "", + "parameterTypes": [] + } + ], + "condition": { + "typeReachable": "org.bouncycastle.jce.provider.BouncyCastleProvider" + } + }, + { + "name": "org.bouncycastle.jcajce.provider.asymmetric.GOST$Mappings", + "methods": [ + { + "name": "", + "parameterTypes": [] + } + ], + "condition": { + "typeReachable": "org.bouncycastle.jce.provider.BouncyCastleProvider" + } + }, + { + "name": "org.bouncycastle.jcajce.provider.asymmetric.IES$Mappings", + "methods": [ + { + "name": "", + "parameterTypes": [] + } + ], + "condition": { + "typeReachable": "org.bouncycastle.jce.provider.BouncyCastleProvider" + } + }, + { + "name": "org.bouncycastle.jcajce.provider.asymmetric.LMS$Mappings", + "methods": [ + { + "name": "", + "parameterTypes": [] + } + ], + "condition": { + "typeReachable": "org.bouncycastle.jce.provider.BouncyCastleProvider" + } + }, + { + "name": "org.bouncycastle.jcajce.provider.asymmetric.NTRU$Mappings", + "methods": [ + { + "name": "", + "parameterTypes": [] + } + ], + "condition": { + "typeReachable": "org.bouncycastle.jce.provider.BouncyCastleProvider" + } + }, + { + "name": "org.bouncycastle.jcajce.provider.asymmetric.RSA$Mappings", + "methods": [ + { + "name": "", + "parameterTypes": [] + } + ], + "condition": { + "typeReachable": "org.bouncycastle.jce.provider.BouncyCastleProvider" + } + }, + { + "name": "org.bouncycastle.jcajce.provider.asymmetric.SPHINCSPlus$Mappings", + "methods": [ + { + "name": "", + "parameterTypes": [] + } + ], + "condition": { + "typeReachable": "org.bouncycastle.jce.provider.BouncyCastleProvider" + } + }, + { + "name": "org.bouncycastle.jcajce.provider.asymmetric.X509$Mappings", + "methods": [ + { + "name": "", + "parameterTypes": [] + } + ], + "condition": { + "typeReachable": "org.bouncycastle.jce.provider.BouncyCastleProvider" + } + }, + { + "name": "org.bouncycastle.jcajce.provider.asymmetric.ec.KeyFactorySpi$ECDSA", + "methods": [ + { + "name": "", + "parameterTypes": [] + } + ], + "condition": { + "typeReachable": "org.bouncycastle.jce.provider.BouncyCastleProvider" + } + }, + { + "name": "org.bouncycastle.jcajce.provider.asymmetric.ec.SignatureSpi$ecDSA256", + "methods": [ + { + "name": "", + "parameterTypes": [] + } + ], + "condition": { + "typeReachable": "org.bouncycastle.jce.provider.BouncyCastleProvider" + } + }, + { + "name": "org.bouncycastle.jcajce.provider.asymmetric.dsa.KeyFactorySpi", + "methods": [ + { + "name": "", + "parameterTypes": [] + } + ], + "condition": { + "typeReachable": "org.bouncycastle.jce.provider.BouncyCastleProvider" + } + }, + { + "name": "org.bouncycastle.jcajce.provider.asymmetric.rsa.KeyFactorySpi", + "methods": [ + { + "name": "", + "parameterTypes": [] + } + ], + "condition": { + "typeReachable": "org.bouncycastle.jce.provider.BouncyCastleProvider" + } + }, + { + "name": "org.bouncycastle.jcajce.provider.digest.Blake2b$Blake2b160", + "methods": [ + { + "name": "", + "parameterTypes": [] + } + ], + "condition": { + "typeReachable": "org.bouncycastle.jce.provider.BouncyCastleProvider" + } + }, + { + "name": "org.bouncycastle.jcajce.provider.digest.Blake2b$Blake2b256", + "methods": [ + { + "name": "", + "parameterTypes": [] + } + ], + "condition": { + "typeReachable": "org.bouncycastle.jce.provider.BouncyCastleProvider" + } + }, + { + "name": "org.bouncycastle.jcajce.provider.digest.Blake2b$Blake2b384", + "methods": [ + { + "name": "", + "parameterTypes": [] + } + ], + "condition": { + "typeReachable": "org.bouncycastle.jce.provider.BouncyCastleProvider" + } + }, + { + "name": "org.bouncycastle.jcajce.provider.digest.Blake2b$Blake2b512", + "methods": [ + { + "name": "", + "parameterTypes": [] + } + ], + "condition": { + "typeReachable": "org.bouncycastle.jce.provider.BouncyCastleProvider" + } + }, + { + "name": "org.bouncycastle.jcajce.provider.digest.Blake2b$Mappings", + "methods": [ + { + "name": "", + "parameterTypes": [] + } + ], + "condition": { + "typeReachable": "org.bouncycastle.jce.provider.BouncyCastleProvider" + } + }, + { + "name": "org.bouncycastle.jcajce.provider.digest.Blake2s$Blake2s128", + "methods": [ + { + "name": "", + "parameterTypes": [] + } + ], + "condition": { + "typeReachable": "org.bouncycastle.jce.provider.BouncyCastleProvider" + } + }, + { + "name": "org.bouncycastle.jcajce.provider.digest.Blake2s$Blake2s160", + "methods": [ + { + "name": "", + "parameterTypes": [] + } + ], + "condition": { + "typeReachable": "org.bouncycastle.jce.provider.BouncyCastleProvider" + } + }, + { + "name": "org.bouncycastle.jcajce.provider.digest.Blake2s$Blake2s224", + "methods": [ + { + "name": "", + "parameterTypes": [] + } + ], + "condition": { + "typeReachable": "org.bouncycastle.jce.provider.BouncyCastleProvider" + } + }, + { + "name": "org.bouncycastle.jcajce.provider.digest.Blake2s$Blake2s256", + "methods": [ + { + "name": "", + "parameterTypes": [] + } + ], + "condition": { + "typeReachable": "org.bouncycastle.jce.provider.BouncyCastleProvider" + } + }, + { + "name": "org.bouncycastle.jcajce.provider.digest.Blake2s$Mappings", + "methods": [ + { + "name": "", + "parameterTypes": [] + } + ], + "condition": { + "typeReachable": "org.bouncycastle.jce.provider.BouncyCastleProvider" + } + }, + { + "name": "org.bouncycastle.jcajce.provider.digest.Blake3$Blake3_256", + "methods": [ + { + "name": "", + "parameterTypes": [] + } + ], + "condition": { + "typeReachable": "org.bouncycastle.jce.provider.BouncyCastleProvider" + } + }, + { + "name": "org.bouncycastle.jcajce.provider.digest.Blake3$Mappings", + "methods": [ + { + "name": "", + "parameterTypes": [] + } + ], + "condition": { + "typeReachable": "org.bouncycastle.jce.provider.BouncyCastleProvider" + } + }, + { + "name": "org.bouncycastle.jcajce.provider.digest.DSTU7564$Digest256", + "methods": [ + { + "name": "", + "parameterTypes": [] + } + ], + "condition": { + "typeReachable": "org.bouncycastle.jce.provider.BouncyCastleProvider" + } + }, + { + "name": "org.bouncycastle.jcajce.provider.digest.DSTU7564$Digest384", + "methods": [ + { + "name": "", + "parameterTypes": [] + } + ], + "condition": { + "typeReachable": "org.bouncycastle.jce.provider.BouncyCastleProvider" + } + }, + { + "name": "org.bouncycastle.jcajce.provider.digest.DSTU7564$Digest512", + "methods": [ + { + "name": "", + "parameterTypes": [] + } + ], + "condition": { + "typeReachable": "org.bouncycastle.jce.provider.BouncyCastleProvider" + } + }, + { + "name": "org.bouncycastle.jcajce.provider.digest.DSTU7564$Mappings", + "methods": [ + { + "name": "", + "parameterTypes": [] + } + ], + "condition": { + "typeReachable": "org.bouncycastle.jce.provider.BouncyCastleProvider" + } + }, + { + "name": "org.bouncycastle.jcajce.provider.digest.GOST3411$Digest", + "methods": [ + { + "name": "", + "parameterTypes": [] + } + ], + "condition": { + "typeReachable": "org.bouncycastle.jce.provider.BouncyCastleProvider" + } + }, + { + "name": "org.bouncycastle.jcajce.provider.digest.GOST3411$Digest2012_256", + "methods": [ + { + "name": "", + "parameterTypes": [] + } + ], + "condition": { + "typeReachable": "org.bouncycastle.jce.provider.BouncyCastleProvider" + } + }, + { + "name": "org.bouncycastle.jcajce.provider.digest.GOST3411$Digest2012_512", + "methods": [ + { + "name": "", + "parameterTypes": [] + } + ], + "condition": { + "typeReachable": "org.bouncycastle.jce.provider.BouncyCastleProvider" + } + }, + { + "name": "org.bouncycastle.jcajce.provider.digest.GOST3411$Mappings", + "methods": [ + { + "name": "", + "parameterTypes": [] + } + ], + "condition": { + "typeReachable": "org.bouncycastle.jce.provider.BouncyCastleProvider" + } + }, + { + "name": "org.bouncycastle.jcajce.provider.digest.Haraka$Digest256", + "methods": [ + { + "name": "", + "parameterTypes": [] + } + ], + "condition": { + "typeReachable": "org.bouncycastle.jce.provider.BouncyCastleProvider" + } + }, + { + "name": "org.bouncycastle.jcajce.provider.digest.Haraka$Digest512", + "methods": [ + { + "name": "", + "parameterTypes": [] + } + ], + "condition": { + "typeReachable": "org.bouncycastle.jce.provider.BouncyCastleProvider" + } + }, + { + "name": "org.bouncycastle.jcajce.provider.digest.Haraka$Mappings", + "methods": [ + { + "name": "", + "parameterTypes": [] + } + ], + "condition": { + "typeReachable": "org.bouncycastle.jce.provider.BouncyCastleProvider" + } + }, + { + "name": "org.bouncycastle.jcajce.provider.digest.Keccak$Digest224", + "methods": [ + { + "name": "", + "parameterTypes": [] + } + ], + "condition": { + "typeReachable": "org.bouncycastle.jce.provider.BouncyCastleProvider" + } + }, + { + "name": "org.bouncycastle.jcajce.provider.digest.Keccak$Digest256", + "methods": [ + { + "name": "", + "parameterTypes": [] + } + ], + "condition": { + "typeReachable": "org.bouncycastle.jce.provider.BouncyCastleProvider" + } + }, + { + "name": "org.bouncycastle.jcajce.provider.digest.Keccak$Digest288", + "methods": [ + { + "name": "", + "parameterTypes": [] + } + ], + "condition": { + "typeReachable": "org.bouncycastle.jce.provider.BouncyCastleProvider" + } + }, + { + "name": "org.bouncycastle.jcajce.provider.digest.Keccak$Digest384", + "methods": [ + { + "name": "", + "parameterTypes": [] + } + ], + "condition": { + "typeReachable": "org.bouncycastle.jce.provider.BouncyCastleProvider" + } + }, + { + "name": "org.bouncycastle.jcajce.provider.digest.Keccak$Digest512", + "methods": [ + { + "name": "", + "parameterTypes": [] + } + ], + "condition": { + "typeReachable": "org.bouncycastle.jce.provider.BouncyCastleProvider" + } + }, + { + "name": "org.bouncycastle.jcajce.provider.digest.Keccak$Mappings", + "methods": [ + { + "name": "", + "parameterTypes": [] + } + ], + "condition": { + "typeReachable": "org.bouncycastle.jce.provider.BouncyCastleProvider" + } + }, + { + "name": "org.bouncycastle.jcajce.provider.digest.MD2$Mappings", + "methods": [ + { + "name": "", + "parameterTypes": [] + } + ], + "condition": { + "typeReachable": "org.bouncycastle.jce.provider.BouncyCastleProvider" + } + }, + { + "name": "org.bouncycastle.jcajce.provider.digest.MD4$Digest", + "methods": [ + { + "name": "", + "parameterTypes": [] + } + ], + "condition": { + "typeReachable": "org.bouncycastle.jce.provider.BouncyCastleProvider" + } + }, + { + "name": "org.bouncycastle.jcajce.provider.digest.MD4$Mappings", + "methods": [ + { + "name": "", + "parameterTypes": [] + } + ], + "condition": { + "typeReachable": "org.bouncycastle.jce.provider.BouncyCastleProvider" + } + }, + { + "name": "org.bouncycastle.jcajce.provider.digest.MD5$Mappings", + "methods": [ + { + "name": "", + "parameterTypes": [] + } + ], + "condition": { + "typeReachable": "org.bouncycastle.jce.provider.BouncyCastleProvider" + } + }, + { + "name": "org.bouncycastle.jcajce.provider.digest.RIPEMD128$Digest", + "methods": [ + { + "name": "", + "parameterTypes": [] + } + ], + "condition": { + "typeReachable": "org.bouncycastle.jce.provider.BouncyCastleProvider" + } + }, + { + "name": "org.bouncycastle.jcajce.provider.digest.RIPEMD128$Mappings", + "methods": [ + { + "name": "", + "parameterTypes": [] + } + ], + "condition": { + "typeReachable": "org.bouncycastle.jce.provider.BouncyCastleProvider" + } + }, + { + "name": "org.bouncycastle.jcajce.provider.digest.RIPEMD160$Digest", + "methods": [ + { + "name": "", + "parameterTypes": [] + } + ], + "condition": { + "typeReachable": "org.bouncycastle.jce.provider.BouncyCastleProvider" + } + }, + { + "name": "org.bouncycastle.jcajce.provider.digest.RIPEMD160$Mappings", + "methods": [ + { + "name": "", + "parameterTypes": [] + } + ], + "condition": { + "typeReachable": "org.bouncycastle.jce.provider.BouncyCastleProvider" + } + }, + { + "name": "org.bouncycastle.jcajce.provider.digest.RIPEMD256$Digest", + "methods": [ + { + "name": "", + "parameterTypes": [] + } + ], + "condition": { + "typeReachable": "org.bouncycastle.jce.provider.BouncyCastleProvider" + } + }, + { + "name": "org.bouncycastle.jcajce.provider.digest.RIPEMD256$Mappings", + "methods": [ + { + "name": "", + "parameterTypes": [] + } + ], + "condition": { + "typeReachable": "org.bouncycastle.jce.provider.BouncyCastleProvider" + } + }, + { + "name": "org.bouncycastle.jcajce.provider.digest.RIPEMD320$Digest", + "methods": [ + { + "name": "", + "parameterTypes": [] + } + ], + "condition": { + "typeReachable": "org.bouncycastle.jce.provider.BouncyCastleProvider" + } + }, + { + "name": "org.bouncycastle.jcajce.provider.digest.RIPEMD320$Mappings", + "methods": [ + { + "name": "", + "parameterTypes": [] + } + ], + "condition": { + "typeReachable": "org.bouncycastle.jce.provider.BouncyCastleProvider" + } + }, + { + "name": "org.bouncycastle.jcajce.provider.digest.SHA1$Mappings", + "methods": [ + { + "name": "", + "parameterTypes": [] + } + ], + "condition": { + "typeReachable": "org.bouncycastle.jce.provider.BouncyCastleProvider" + } + }, + { + "name": "org.bouncycastle.jcajce.provider.digest.SHA224$Mappings", + "methods": [ + { + "name": "", + "parameterTypes": [] + } + ], + "condition": { + "typeReachable": "org.bouncycastle.jce.provider.BouncyCastleProvider" + } + }, + { + "name": "org.bouncycastle.jcajce.provider.digest.SHA256$Mappings", + "methods": [ + { + "name": "", + "parameterTypes": [] + } + ], + "condition": { + "typeReachable": "org.bouncycastle.jce.provider.BouncyCastleProvider" + } + }, + { + "name": "org.bouncycastle.jcajce.provider.digest.SHA3$DigestParallelHash128_256", + "methods": [ + { + "name": "", + "parameterTypes": [] + } + ], + "condition": { + "typeReachable": "org.bouncycastle.jce.provider.BouncyCastleProvider" + } + }, + { + "name": "org.bouncycastle.jcajce.provider.digest.SHA3$DigestParallelHash256_512", + "methods": [ + { + "name": "", + "parameterTypes": [] + } + ], + "condition": { + "typeReachable": "org.bouncycastle.jce.provider.BouncyCastleProvider" + } + }, + { + "name": "org.bouncycastle.jcajce.provider.digest.SHA3$DigestShake128_256", + "methods": [ + { + "name": "", + "parameterTypes": [] + } + ], + "condition": { + "typeReachable": "org.bouncycastle.jce.provider.BouncyCastleProvider" + } + }, + { + "name": "org.bouncycastle.jcajce.provider.digest.SHA3$DigestShake256_512", + "methods": [ + { + "name": "", + "parameterTypes": [] + } + ], + "condition": { + "typeReachable": "org.bouncycastle.jce.provider.BouncyCastleProvider" + } + }, + { + "name": "org.bouncycastle.jcajce.provider.digest.SHA3$DigestTupleHash128_256", + "methods": [ + { + "name": "", + "parameterTypes": [] + } + ], + "condition": { + "typeReachable": "org.bouncycastle.jce.provider.BouncyCastleProvider" + } + }, + { + "name": "org.bouncycastle.jcajce.provider.digest.SHA3$DigestTupleHash256_512", + "methods": [ + { + "name": "", + "parameterTypes": [] + } + ], + "condition": { + "typeReachable": "org.bouncycastle.jce.provider.BouncyCastleProvider" + } + }, + { + "name": "org.bouncycastle.jcajce.provider.digest.SHA3$Mappings", + "methods": [ + { + "name": "", + "parameterTypes": [] + } + ], + "condition": { + "typeReachable": "org.bouncycastle.jce.provider.BouncyCastleProvider" + } + }, + { + "name": "org.bouncycastle.jcajce.provider.digest.SHA384$Mappings", + "methods": [ + { + "name": "", + "parameterTypes": [] + } + ], + "condition": { + "typeReachable": "org.bouncycastle.jce.provider.BouncyCastleProvider" + } + }, + { + "name": "org.bouncycastle.jcajce.provider.digest.SHA512$Mappings", + "methods": [ + { + "name": "", + "parameterTypes": [] + } + ], + "condition": { + "typeReachable": "org.bouncycastle.jce.provider.BouncyCastleProvider" + } + }, + { + "name": "org.bouncycastle.jcajce.provider.digest.SM3$Digest", + "methods": [ + { + "name": "", + "parameterTypes": [] + } + ], + "condition": { + "typeReachable": "org.bouncycastle.jce.provider.BouncyCastleProvider" + } + }, + { + "name": "org.bouncycastle.jcajce.provider.digest.SM3$Mappings", + "methods": [ + { + "name": "", + "parameterTypes": [] + } + ], + "condition": { + "typeReachable": "org.bouncycastle.jce.provider.BouncyCastleProvider" + } + }, + { + "name": "org.bouncycastle.jcajce.provider.digest.Skein$Digest_1024_1024", + "methods": [ + { + "name": "", + "parameterTypes": [] + } + ], + "condition": { + "typeReachable": "org.bouncycastle.jce.provider.BouncyCastleProvider" + } + }, + { + "name": "org.bouncycastle.jcajce.provider.digest.Skein$Digest_1024_384", + "methods": [ + { + "name": "", + "parameterTypes": [] + } + ], + "condition": { + "typeReachable": "org.bouncycastle.jce.provider.BouncyCastleProvider" + } + }, + { + "name": "org.bouncycastle.jcajce.provider.digest.Skein$Digest_1024_512", + "methods": [ + { + "name": "", + "parameterTypes": [] + } + ], + "condition": { + "typeReachable": "org.bouncycastle.jce.provider.BouncyCastleProvider" + } + }, + { + "name": "org.bouncycastle.jcajce.provider.digest.Skein$Digest_256_128", + "methods": [ + { + "name": "", + "parameterTypes": [] + } + ], + "condition": { + "typeReachable": "org.bouncycastle.jce.provider.BouncyCastleProvider" + } + }, + { + "name": "org.bouncycastle.jcajce.provider.digest.Skein$Digest_256_160", + "methods": [ + { + "name": "", + "parameterTypes": [] + } + ], + "condition": { + "typeReachable": "org.bouncycastle.jce.provider.BouncyCastleProvider" + } + }, + { + "name": "org.bouncycastle.jcajce.provider.digest.Skein$Digest_256_224", + "methods": [ + { + "name": "", + "parameterTypes": [] + } + ], + "condition": { + "typeReachable": "org.bouncycastle.jce.provider.BouncyCastleProvider" + } + }, + { + "name": "org.bouncycastle.jcajce.provider.digest.Skein$Digest_256_256", + "methods": [ + { + "name": "", + "parameterTypes": [] + } + ], + "condition": { + "typeReachable": "org.bouncycastle.jce.provider.BouncyCastleProvider" + } + }, + { + "name": "org.bouncycastle.jcajce.provider.digest.Skein$Digest_512_128", + "methods": [ + { + "name": "", + "parameterTypes": [] + } + ], + "condition": { + "typeReachable": "org.bouncycastle.jce.provider.BouncyCastleProvider" + } + }, + { + "name": "org.bouncycastle.jcajce.provider.digest.Skein$Digest_512_160", + "methods": [ + { + "name": "", + "parameterTypes": [] + } + ], + "condition": { + "typeReachable": "org.bouncycastle.jce.provider.BouncyCastleProvider" + } + }, + { + "name": "org.bouncycastle.jcajce.provider.digest.Skein$Digest_512_224", + "methods": [ + { + "name": "", + "parameterTypes": [] + } + ], + "condition": { + "typeReachable": "org.bouncycastle.jce.provider.BouncyCastleProvider" + } + }, + { + "name": "org.bouncycastle.jcajce.provider.digest.Skein$Digest_512_256", + "methods": [ + { + "name": "", + "parameterTypes": [] + } + ], + "condition": { + "typeReachable": "org.bouncycastle.jce.provider.BouncyCastleProvider" + } + }, + { + "name": "org.bouncycastle.jcajce.provider.digest.Skein$Digest_512_384", + "methods": [ + { + "name": "", + "parameterTypes": [] + } + ], + "condition": { + "typeReachable": "org.bouncycastle.jce.provider.BouncyCastleProvider" + } + }, + { + "name": "org.bouncycastle.jcajce.provider.digest.Skein$Digest_512_512", + "methods": [ + { + "name": "", + "parameterTypes": [] + } + ], + "condition": { + "typeReachable": "org.bouncycastle.jce.provider.BouncyCastleProvider" + } + }, + { + "name": "org.bouncycastle.jcajce.provider.digest.Skein$Mappings", + "methods": [ + { + "name": "", + "parameterTypes": [] + } + ], + "condition": { + "typeReachable": "org.bouncycastle.jce.provider.BouncyCastleProvider" + } + }, + { + "name": "org.bouncycastle.jcajce.provider.digest.Tiger$Digest", + "methods": [ + { + "name": "", + "parameterTypes": [] + } + ], + "condition": { + "typeReachable": "org.bouncycastle.jce.provider.BouncyCastleProvider" + } + }, + { + "name": "org.bouncycastle.jcajce.provider.digest.Tiger$Mappings", + "methods": [ + { + "name": "", + "parameterTypes": [] + } + ], + "condition": { + "typeReachable": "org.bouncycastle.jce.provider.BouncyCastleProvider" + } + }, + { + "name": "org.bouncycastle.jcajce.provider.digest.Whirlpool$Digest", + "methods": [ + { + "name": "", + "parameterTypes": [] + } + ], + "condition": { + "typeReachable": "org.bouncycastle.jce.provider.BouncyCastleProvider" + } + }, + { + "name": "org.bouncycastle.jcajce.provider.digest.Whirlpool$Mappings", + "methods": [ + { + "name": "", + "parameterTypes": [] + } + ], + "condition": { + "typeReachable": "org.bouncycastle.jce.provider.BouncyCastleProvider" + } + }, + { + "name": "org.bouncycastle.jcajce.provider.drbg.DRBG$Mappings", + "methods": [ + { + "name": "", + "parameterTypes": [] + } + ], + "condition": { + "typeReachable": "org.bouncycastle.jce.provider.BouncyCastleProvider" + } + }, + { + "name": "org.bouncycastle.jcajce.provider.keystore.BC$Mappings", + "methods": [ + { + "name": "", + "parameterTypes": [] + } + ], + "condition": { + "typeReachable": "org.bouncycastle.jce.provider.BouncyCastleProvider" + } + }, + { + "name": "org.bouncycastle.jcajce.provider.keystore.BCFKS$Mappings", + "methods": [ + { + "name": "", + "parameterTypes": [] + } + ], + "condition": { + "typeReachable": "org.bouncycastle.jce.provider.BouncyCastleProvider" + } + }, + { + "name": "org.bouncycastle.jcajce.provider.keystore.PKCS12$Mappings", + "methods": [ + { + "name": "", + "parameterTypes": [] + } + ], + "condition": { + "typeReachable": "org.bouncycastle.jce.provider.BouncyCastleProvider" + } + }, + { + "name": "org.bouncycastle.jcajce.provider.symmetric.AES$AlgParams", + "methods": [ + { + "name": "", + "parameterTypes": [] + } + ], + "condition": { + "typeReachable": "org.bouncycastle.jce.provider.BouncyCastleProvider" + } + }, + { + "name": "org.bouncycastle.jcajce.provider.symmetric.AES$ECB", + "methods": [ + { + "name": "", + "parameterTypes": [] + } + ], + "condition": { + "typeReachable": "org.bouncycastle.jce.provider.BouncyCastleProvider" + } + }, + { + "name": "org.bouncycastle.jcajce.provider.symmetric.AES$CBC", + "methods": [ + { + "name": "", + "parameterTypes": [] + } + ], + "condition": { + "typeReachable": "org.bouncycastle.jce.provider.BouncyCastleProvider" + } + }, + { + "name": "org.bouncycastle.jcajce.provider.symmetric.AES$CBC128", + "methods": [ + { + "name": "", + "parameterTypes": [] + } + ], + "condition": { + "typeReachable": "org.bouncycastle.jce.provider.BouncyCastleProvider" + } + }, + { + "name": "org.bouncycastle.jcajce.provider.symmetric.AES$CBC192", + "methods": [ + { + "name": "", + "parameterTypes": [] + } + ], + "condition": { + "typeReachable": "org.bouncycastle.jce.provider.BouncyCastleProvider" + } + }, + { + "name": "org.bouncycastle.jcajce.provider.symmetric.AES$CBC256", + "methods": [ + { + "name": "", + "parameterTypes": [] + } + ], + "condition": { + "typeReachable": "org.bouncycastle.jce.provider.BouncyCastleProvider" + } + }, + { + "name": "org.bouncycastle.jcajce.provider.symmetric.AES$PBEWithMD5And256BitAESCBCOpenSSL", + "methods": [ + { + "name": "", + "parameterTypes": [] + } + ], + "condition": { + "typeReachable": "org.bouncycastle.jce.provider.BouncyCastleProvider" + } + }, + { + "name": "org.bouncycastle.jcajce.provider.symmetric.AES$Mappings", + "methods": [ + { + "name": "", + "parameterTypes": [] + } + ], + "condition": { + "typeReachable": "org.bouncycastle.jce.provider.BouncyCastleProvider" + } + }, + { + "name": "org.bouncycastle.jcajce.provider.symmetric.ARC4$Mappings", + "methods": [ + { + "name": "", + "parameterTypes": [] + } + ], + "condition": { + "typeReachable": "org.bouncycastle.jce.provider.BouncyCastleProvider" + } + }, + { + "name": "org.bouncycastle.jcajce.provider.symmetric.ARIA$Mappings", + "methods": [ + { + "name": "", + "parameterTypes": [] + } + ], + "condition": { + "typeReachable": "org.bouncycastle.jce.provider.BouncyCastleProvider" + } + }, + { + "name": "org.bouncycastle.jcajce.provider.symmetric.Blowfish$Mappings", + "methods": [ + { + "name": "", + "parameterTypes": [] + } + ], + "condition": { + "typeReachable": "org.bouncycastle.jce.provider.BouncyCastleProvider" + } + }, + { + "name": "org.bouncycastle.jcajce.provider.symmetric.CAST5$Mappings", + "methods": [ + { + "name": "", + "parameterTypes": [] + } + ], + "condition": { + "typeReachable": "org.bouncycastle.jce.provider.BouncyCastleProvider" + } + }, + { + "name": "org.bouncycastle.jcajce.provider.symmetric.CAST6$Mappings", + "methods": [ + { + "name": "", + "parameterTypes": [] + } + ], + "condition": { + "typeReachable": "org.bouncycastle.jce.provider.BouncyCastleProvider" + } + }, + { + "name": "org.bouncycastle.jcajce.provider.symmetric.Camellia$Mappings", + "methods": [ + { + "name": "", + "parameterTypes": [] + } + ], + "condition": { + "typeReachable": "org.bouncycastle.jce.provider.BouncyCastleProvider" + } + }, + { + "name": "org.bouncycastle.jcajce.provider.symmetric.ChaCha$Mappings", + "methods": [ + { + "name": "", + "parameterTypes": [] + } + ], + "condition": { + "typeReachable": "org.bouncycastle.jce.provider.BouncyCastleProvider" + } + }, + { + "name": "org.bouncycastle.jcajce.provider.symmetric.DES$Mappings", + "methods": [ + { + "name": "", + "parameterTypes": [] + } + ], + "condition": { + "typeReachable": "org.bouncycastle.jce.provider.BouncyCastleProvider" + } + }, + { + "name": "org.bouncycastle.jcajce.provider.symmetric.DESede$Mappings", + "methods": [ + { + "name": "", + "parameterTypes": [] + } + ], + "condition": { + "typeReachable": "org.bouncycastle.jce.provider.BouncyCastleProvider" + } + }, + { + "name": "org.bouncycastle.jcajce.provider.symmetric.DSTU7624$Mappings", + "methods": [ + { + "name": "", + "parameterTypes": [] + } + ], + "condition": { + "typeReachable": "org.bouncycastle.jce.provider.BouncyCastleProvider" + } + }, + { + "name": "org.bouncycastle.jcajce.provider.symmetric.GOST28147$Mappings", + "methods": [ + { + "name": "", + "parameterTypes": [] + } + ], + "condition": { + "typeReachable": "org.bouncycastle.jce.provider.BouncyCastleProvider" + } + }, + { + "name": "org.bouncycastle.jcajce.provider.symmetric.GOST3412_2015$Mappings", + "methods": [ + { + "name": "", + "parameterTypes": [] + } + ], + "condition": { + "typeReachable": "org.bouncycastle.jce.provider.BouncyCastleProvider" + } + }, + { + "name": "org.bouncycastle.jcajce.provider.symmetric.Grain128$Mappings", + "methods": [ + { + "name": "", + "parameterTypes": [] + } + ], + "condition": { + "typeReachable": "org.bouncycastle.jce.provider.BouncyCastleProvider" + } + }, + { + "name": "org.bouncycastle.jcajce.provider.symmetric.Grainv1$Mappings", + "methods": [ + { + "name": "", + "parameterTypes": [] + } + ], + "condition": { + "typeReachable": "org.bouncycastle.jce.provider.BouncyCastleProvider" + } + }, + { + "name": "org.bouncycastle.jcajce.provider.symmetric.HC128$Mappings", + "methods": [ + { + "name": "", + "parameterTypes": [] + } + ], + "condition": { + "typeReachable": "org.bouncycastle.jce.provider.BouncyCastleProvider" + } + }, + { + "name": "org.bouncycastle.jcajce.provider.symmetric.HC256$Mappings", + "methods": [ + { + "name": "", + "parameterTypes": [] + } + ], + "condition": { + "typeReachable": "org.bouncycastle.jce.provider.BouncyCastleProvider" + } + }, + { + "name": "org.bouncycastle.jcajce.provider.symmetric.IDEA$Mappings", + "methods": [ + { + "name": "", + "parameterTypes": [] + } + ], + "condition": { + "typeReachable": "org.bouncycastle.jce.provider.BouncyCastleProvider" + } + }, + { + "name": "org.bouncycastle.jcajce.provider.symmetric.Noekeon$Mappings", + "methods": [ + { + "name": "", + "parameterTypes": [] + } + ], + "condition": { + "typeReachable": "org.bouncycastle.jce.provider.BouncyCastleProvider" + } + }, + { + "name": "org.bouncycastle.jcajce.provider.symmetric.OpenSSLPBKDF$Mappings", + "methods": [ + { + "name": "", + "parameterTypes": [] + } + ], + "condition": { + "typeReachable": "org.bouncycastle.jce.provider.BouncyCastleProvider" + } + }, + { + "name": "org.bouncycastle.jcajce.provider.symmetric.PBEPBKDF1$Mappings", + "methods": [ + { + "name": "", + "parameterTypes": [] + } + ], + "condition": { + "typeReachable": "org.bouncycastle.jce.provider.BouncyCastleProvider" + } + }, + { + "name": "org.bouncycastle.jcajce.provider.symmetric.PBEPBKDF2$Mappings", + "methods": [ + { + "name": "", + "parameterTypes": [] + } + ], + "condition": { + "typeReachable": "org.bouncycastle.jce.provider.BouncyCastleProvider" + } + }, + { + "name": "org.bouncycastle.jcajce.provider.symmetric.PBEPBKDF2$PBKDF2withSHA256", + "methods": [ + { + "name": "", + "parameterTypes": [] + } + ], + "condition": { + "typeReachable": "org.bouncycastle.jce.provider.BouncyCastleProvider" + } + }, + { + "name": "org.bouncycastle.jcajce.provider.symmetric.PBEPKCS12$Mappings", + "methods": [ + { + "name": "", + "parameterTypes": [] + } + ], + "condition": { + "typeReachable": "org.bouncycastle.jce.provider.BouncyCastleProvider" + } + }, + { + "name": "org.bouncycastle.jcajce.provider.symmetric.Poly1305$Mappings", + "methods": [ + { + "name": "", + "parameterTypes": [] + } + ], + "condition": { + "typeReachable": "org.bouncycastle.jce.provider.BouncyCastleProvider" + } + }, + { + "name": "org.bouncycastle.jcajce.provider.symmetric.RC2$Mappings", + "methods": [ + { + "name": "", + "parameterTypes": [] + } + ], + "condition": { + "typeReachable": "org.bouncycastle.jce.provider.BouncyCastleProvider" + } + }, + { + "name": "org.bouncycastle.jcajce.provider.symmetric.RC5$Mappings", + "methods": [ + { + "name": "", + "parameterTypes": [] + } + ], + "condition": { + "typeReachable": "org.bouncycastle.jce.provider.BouncyCastleProvider" + } + }, + { + "name": "org.bouncycastle.jcajce.provider.symmetric.RC6$Mappings", + "methods": [ + { + "name": "", + "parameterTypes": [] + } + ], + "condition": { + "typeReachable": "org.bouncycastle.jce.provider.BouncyCastleProvider" + } + }, + { + "name": "org.bouncycastle.jcajce.provider.symmetric.Rijndael$Mappings", + "methods": [ + { + "name": "", + "parameterTypes": [] + } + ], + "condition": { + "typeReachable": "org.bouncycastle.jce.provider.BouncyCastleProvider" + } + }, + { + "name": "org.bouncycastle.jcajce.provider.symmetric.SCRYPT$Mappings", + "methods": [ + { + "name": "", + "parameterTypes": [] + } + ], + "condition": { + "typeReachable": "org.bouncycastle.jce.provider.BouncyCastleProvider" + } + }, + { + "name": "org.bouncycastle.jcajce.provider.symmetric.SEED$Mappings", + "methods": [ + { + "name": "", + "parameterTypes": [] + } + ], + "condition": { + "typeReachable": "org.bouncycastle.jce.provider.BouncyCastleProvider" + } + }, + { + "name": "org.bouncycastle.jcajce.provider.symmetric.SM4$Mappings", + "methods": [ + { + "name": "", + "parameterTypes": [] + } + ], + "condition": { + "typeReachable": "org.bouncycastle.jce.provider.BouncyCastleProvider" + } + }, + { + "name": "org.bouncycastle.jcajce.provider.symmetric.Salsa20$Mappings", + "methods": [ + { + "name": "", + "parameterTypes": [] + } + ], + "condition": { + "typeReachable": "org.bouncycastle.jce.provider.BouncyCastleProvider" + } + }, + { + "name": "org.bouncycastle.jcajce.provider.symmetric.Serpent$Mappings", + "methods": [ + { + "name": "", + "parameterTypes": [] + } + ], + "condition": { + "typeReachable": "org.bouncycastle.jce.provider.BouncyCastleProvider" + } + }, + { + "name": "org.bouncycastle.jcajce.provider.symmetric.Shacal2$Mappings", + "methods": [ + { + "name": "", + "parameterTypes": [] + } + ], + "condition": { + "typeReachable": "org.bouncycastle.jce.provider.BouncyCastleProvider" + } + }, + { + "name": "org.bouncycastle.jcajce.provider.symmetric.SipHash$Mappings", + "methods": [ + { + "name": "", + "parameterTypes": [] + } + ], + "condition": { + "typeReachable": "org.bouncycastle.jce.provider.BouncyCastleProvider" + } + }, + { + "name": "org.bouncycastle.jcajce.provider.symmetric.SipHash128$Mappings", + "methods": [ + { + "name": "", + "parameterTypes": [] + } + ], + "condition": { + "typeReachable": "org.bouncycastle.jce.provider.BouncyCastleProvider" + } + }, + { + "name": "org.bouncycastle.jcajce.provider.symmetric.Skipjack$Mappings", + "methods": [ + { + "name": "", + "parameterTypes": [] + } + ], + "condition": { + "typeReachable": "org.bouncycastle.jce.provider.BouncyCastleProvider" + } + }, + { + "name": "org.bouncycastle.jcajce.provider.symmetric.TEA$Mappings", + "methods": [ + { + "name": "", + "parameterTypes": [] + } + ], + "condition": { + "typeReachable": "org.bouncycastle.jce.provider.BouncyCastleProvider" + } + }, + { + "name": "org.bouncycastle.jcajce.provider.symmetric.TLSKDF$Mappings", + "methods": [ + { + "name": "", + "parameterTypes": [] + } + ], + "condition": { + "typeReachable": "org.bouncycastle.jce.provider.BouncyCastleProvider" + } + }, + { + "name": "org.bouncycastle.jcajce.provider.symmetric.Threefish$Mappings", + "methods": [ + { + "name": "", + "parameterTypes": [] + } + ], + "condition": { + "typeReachable": "org.bouncycastle.jce.provider.BouncyCastleProvider" + } + }, + { + "name": "org.bouncycastle.jcajce.provider.symmetric.Twofish$Mappings", + "methods": [ + { + "name": "", + "parameterTypes": [] + } + ], + "condition": { + "typeReachable": "org.bouncycastle.jce.provider.BouncyCastleProvider" + } + }, + { + "name": "org.bouncycastle.jcajce.provider.symmetric.VMPC$Mappings", + "methods": [ + { + "name": "", + "parameterTypes": [] + } + ], + "condition": { + "typeReachable": "org.bouncycastle.jce.provider.BouncyCastleProvider" + } + }, + { + "name": "org.bouncycastle.jcajce.provider.symmetric.VMPCKSA3$Mappings", + "methods": [ + { + "name": "", + "parameterTypes": [] + } + ], + "condition": { + "typeReachable": "org.bouncycastle.jce.provider.BouncyCastleProvider" + } + }, + { + "name": "org.bouncycastle.jcajce.provider.symmetric.XSalsa20$Mappings", + "methods": [ + { + "name": "", + "parameterTypes": [] + } + ], + "condition": { + "typeReachable": "org.bouncycastle.jce.provider.BouncyCastleProvider" + } + }, + { + "name": "org.bouncycastle.jcajce.provider.symmetric.XTEA$Mappings", + "methods": [ + { + "name": "", + "parameterTypes": [] + } + ], + "condition": { + "typeReachable": "org.bouncycastle.jce.provider.BouncyCastleProvider" + } + }, + { + "name": "org.bouncycastle.jcajce.provider.symmetric.Zuc$Mappings", + "methods": [ + { + "name": "", + "parameterTypes": [] + } + ], + "condition": { + "typeReachable": "org.bouncycastle.jce.provider.BouncyCastleProvider" + } + }, + { + "name": "org.bouncycastle.pqc.jcajce.provider.BIKE$Mappings", + "methods": [ + { + "name": "", + "parameterTypes": [] + } + ], + "condition": { + "typeReachable": "org.bouncycastle.jce.provider.BouncyCastleProvider" + } + }, + { + "name": "org.bouncycastle.pqc.jcajce.provider.CMCE$Mappings", + "methods": [ + { + "name": "", + "parameterTypes": [] + } + ], + "condition": { + "typeReachable": "org.bouncycastle.jce.provider.BouncyCastleProvider" + } + }, + { + "name": "org.bouncycastle.pqc.jcajce.provider.Dilithium$Mappings", + "methods": [ + { + "name": "", + "parameterTypes": [] + } + ], + "condition": { + "typeReachable": "org.bouncycastle.jce.provider.BouncyCastleProvider" + } + }, + { + "name": "org.bouncycastle.pqc.jcajce.provider.Falcon$Mappings", + "methods": [ + { + "name": "", + "parameterTypes": [] + } + ], + "condition": { + "typeReachable": "org.bouncycastle.jce.provider.BouncyCastleProvider" + } + }, + { + "name": "org.bouncycastle.pqc.jcajce.provider.Frodo$Mappings", + "methods": [ + { + "name": "", + "parameterTypes": [] + } + ], + "condition": { + "typeReachable": "org.bouncycastle.jce.provider.BouncyCastleProvider" + } + }, + { + "name": "org.bouncycastle.pqc.jcajce.provider.HQC$Mappings", + "methods": [ + { + "name": "", + "parameterTypes": [] + } + ], + "condition": { + "typeReachable": "org.bouncycastle.jce.provider.BouncyCastleProvider" + } + }, + { + "name": "org.bouncycastle.pqc.jcajce.provider.Kyber$Mappings", + "methods": [ + { + "name": "", + "parameterTypes": [] + } + ], + "condition": { + "typeReachable": "org.bouncycastle.jce.provider.BouncyCastleProvider" + } + }, + { + "name": "org.bouncycastle.pqc.jcajce.provider.LMS$Mappings", + "methods": [ + { + "name": "", + "parameterTypes": [] + } + ], + "condition": { + "typeReachable": "org.bouncycastle.jce.provider.BouncyCastleProvider" + } + }, + { + "name": "org.bouncycastle.pqc.jcajce.provider.NH$Mappings", + "methods": [ + { + "name": "", + "parameterTypes": [] + } + ], + "condition": { + "typeReachable": "org.bouncycastle.jce.provider.BouncyCastleProvider" + } + }, + { + "name": "org.bouncycastle.pqc.jcajce.provider.NTRU$Mappings", + "methods": [ + { + "name": "", + "parameterTypes": [] + } + ], + "condition": { + "typeReachable": "org.bouncycastle.jce.provider.BouncyCastleProvider" + } + }, + { + "name": "org.bouncycastle.pqc.jcajce.provider.NTRUPrime$Mappings", + "methods": [ + { + "name": "", + "parameterTypes": [] + } + ], + "condition": { + "typeReachable": "org.bouncycastle.jce.provider.BouncyCastleProvider" + } + }, + { + "name": "org.bouncycastle.pqc.jcajce.provider.Picnic$Mappings", + "methods": [ + { + "name": "", + "parameterTypes": [] + } + ], + "condition": { + "typeReachable": "org.bouncycastle.jce.provider.BouncyCastleProvider" + } + }, + { + "name": "org.bouncycastle.pqc.jcajce.provider.Rainbow$Mappings", + "methods": [ + { + "name": "", + "parameterTypes": [] + } + ], + "condition": { + "typeReachable": "org.bouncycastle.jce.provider.BouncyCastleProvider" + } + }, + { + "name": "org.bouncycastle.pqc.jcajce.provider.SABER$Mappings", + "methods": [ + { + "name": "", + "parameterTypes": [] + } + ], + "condition": { + "typeReachable": "org.bouncycastle.jce.provider.BouncyCastleProvider" + } + }, + { + "name": "org.bouncycastle.pqc.jcajce.provider.SPHINCS$Mappings", + "methods": [ + { + "name": "", + "parameterTypes": [] + } + ], + "condition": { + "typeReachable": "org.bouncycastle.jce.provider.BouncyCastleProvider" + } + }, + { + "name": "org.bouncycastle.pqc.jcajce.provider.SPHINCSPlus$Mappings", + "methods": [ + { + "name": "", + "parameterTypes": [] + } + ], + "condition": { + "typeReachable": "org.bouncycastle.jce.provider.BouncyCastleProvider" + } + }, + { + "name": "org.bouncycastle.pqc.jcajce.provider.XMSS$Mappings", + "methods": [ + { + "name": "", + "parameterTypes": [] + } + ], + "condition": { + "typeReachable": "org.bouncycastle.jce.provider.BouncyCastleProvider" + } + } +] diff --git a/graalpython/com.oracle.graal.python.bouncycastle/src/META-INF/services/com.oracle.graal.python.runtime.crypto.BouncyCastleSupport b/graalpython/com.oracle.graal.python.bouncycastle/src/META-INF/services/com.oracle.graal.python.runtime.crypto.BouncyCastleSupport new file mode 100644 index 0000000000..7bfca52a3e --- /dev/null +++ b/graalpython/com.oracle.graal.python.bouncycastle/src/META-INF/services/com.oracle.graal.python.runtime.crypto.BouncyCastleSupport @@ -0,0 +1 @@ +com.oracle.graal.python.bouncycastle.BouncyCastleSupportImpl diff --git a/graalpython/com.oracle.graal.python.bouncycastle/src/com/oracle/graal/python/bouncycastle/BouncyCastleFeature.java b/graalpython/com.oracle.graal.python.bouncycastle/src/com/oracle/graal/python/bouncycastle/BouncyCastleFeature.java new file mode 100644 index 0000000000..e659675a35 --- /dev/null +++ b/graalpython/com.oracle.graal.python.bouncycastle/src/com/oracle/graal/python/bouncycastle/BouncyCastleFeature.java @@ -0,0 +1,61 @@ +/* + * Copyright (c) 2022, 2026, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * The Universal Permissive License (UPL), Version 1.0 + * + * Subject to the condition set forth below, permission is hereby granted to any + * person obtaining a copy of this software, associated documentation and/or + * data (collectively the "Software"), free of charge and under any and all + * copyright rights in the Software, and any and all patent rights owned or + * freely licensable by each licensor hereunder covering either (i) the + * unmodified Software as contributed to or provided by such licensor, or (ii) + * the Larger Works (as defined below), to deal in both + * + * (a) the Software, and + * + * (b) any piece of software and/or hardware listed in the lrgrwrks.txt file if + * one is included with the Software each a "Larger Work" to which the Software + * is contributed by such licensors), + * + * without restriction, including without limitation the rights to copy, create + * derivative works of, display, perform, and distribute the Software and make, + * use, sell, offer for sale, import, export, have made, and have sold the + * Software and the Larger Work(s), and to sublicense the foregoing rights on + * either these or other terms. + * + * This license is subject to the following condition: + * + * The above copyright notice and either this complete permission notice or at a + * minimum a reference to the UPL must be included in all copies or substantial + * portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ +package com.oracle.graal.python.bouncycastle; + +import java.security.Security; + +import org.bouncycastle.jce.provider.BouncyCastleProvider; +import org.graalvm.nativeimage.ImageSingletons; +import org.graalvm.nativeimage.hosted.Feature; +import org.graalvm.nativeimage.impl.RuntimeClassInitializationSupport; + +public final class BouncyCastleFeature implements Feature { + @Override + public void afterRegistration(AfterRegistrationAccess access) { + RuntimeClassInitializationSupport support = ImageSingletons.lookup(RuntimeClassInitializationSupport.class); + support.initializeAtBuildTime("org.bouncycastle", "security provider"); + support.initializeAtRunTime("org.bouncycastle.jcajce.provider.drbg.DRBG$Default", "RNG"); + support.initializeAtRunTime("org.bouncycastle.jcajce.provider.drbg.DRBG$NonceAndIV", "RNG"); + if (Security.getProvider(BouncyCastleProvider.PROVIDER_NAME) == null) { + Security.addProvider(new BouncyCastleProvider()); + } + } +} diff --git a/graalpython/com.oracle.graal.python.bouncycastle/src/com/oracle/graal/python/bouncycastle/BouncyCastleSupportImpl.java b/graalpython/com.oracle.graal.python.bouncycastle/src/com/oracle/graal/python/bouncycastle/BouncyCastleSupportImpl.java new file mode 100644 index 0000000000..3c5ad556fa --- /dev/null +++ b/graalpython/com.oracle.graal.python.bouncycastle/src/com/oracle/graal/python/bouncycastle/BouncyCastleSupportImpl.java @@ -0,0 +1,122 @@ +/* + * Copyright (c) 2026, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * The Universal Permissive License (UPL), Version 1.0 + * + * Subject to the condition set forth below, permission is hereby granted to any + * person obtaining a copy of this software, associated documentation and/or + * data (collectively the "Software"), free of charge and under any and all + * copyright rights in the Software, and any and all patent rights owned or + * freely licensable by each licensor hereunder covering either (i) the + * unmodified Software as contributed to or provided by such licensor, or (ii) + * the Larger Works (as defined below), to deal in both + * + * (a) the Software, and + * + * (b) any piece of software and/or hardware listed in the lrgrwrks.txt file if + * one is included with the Software each a "Larger Work" to which the Software + * is contributed by such licensors), + * + * without restriction, including without limitation the rights to copy, create + * derivative works of, display, perform, and distribute the Software and make, + * use, sell, offer for sale, import, export, have made, and have sold the + * Software and the Larger Work(s), and to sublicense the foregoing rights on + * either these or other terms. + * + * This license is subject to the following condition: + * + * The above copyright notice and either this complete permission notice or at a + * minimum a reference to the UPL must be included in all copies or substantial + * portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ +package com.oracle.graal.python.bouncycastle; + +import java.io.IOException; +import java.io.StringReader; +import java.security.GeneralSecurityException; +import java.security.MessageDigest; +import java.security.NoSuchAlgorithmException; +import java.security.PrivateKey; +import java.security.Provider; +import java.security.Security; +import java.security.Signature; + +import org.bouncycastle.asn1.pkcs.PrivateKeyInfo; +import org.bouncycastle.jce.provider.BouncyCastleProvider; +import org.bouncycastle.openssl.PEMEncryptedKeyPair; +import org.bouncycastle.openssl.PEMKeyPair; +import org.bouncycastle.openssl.PEMParser; +import org.bouncycastle.openssl.jcajce.JcaPEMKeyConverter; +import org.bouncycastle.openssl.jcajce.JceOpenSSLPKCS8DecryptorProviderBuilder; +import org.bouncycastle.openssl.jcajce.JcePEMDecryptorProviderBuilder; +import org.bouncycastle.operator.OperatorCreationException; +import org.bouncycastle.pkcs.PKCS8EncryptedPrivateKeyInfo; +import org.bouncycastle.pkcs.PKCSException; + +import com.oracle.graal.python.builtins.objects.ssl.CertUtils.NeedsPasswordException; +import com.oracle.graal.python.runtime.crypto.BouncyCastleSupport; + +public final class BouncyCastleSupportImpl implements BouncyCastleSupport { + private static Provider getProvider() { + Provider provider = Security.getProvider(BouncyCastleProvider.PROVIDER_NAME); + if (provider != null) { + return provider; + } + return new BouncyCastleProvider(); + } + + @Override + public PrivateKey loadPrivateKey(char[] password, String pemText) throws IOException, NeedsPasswordException, GeneralSecurityException { + Provider provider = getProvider(); + try (PEMParser pemParser = new PEMParser(new StringReader(pemText))) { + JcaPEMKeyConverter converter = new JcaPEMKeyConverter().setProvider(provider); + Object object; + while ((object = pemParser.readObject()) != null) { + PrivateKeyInfo pkInfo; + if (object instanceof PEMKeyPair) { + pkInfo = ((PEMKeyPair) object).getPrivateKeyInfo(); + } else if (object instanceof PEMEncryptedKeyPair) { + if (password == null) { + throw new NeedsPasswordException(); + } + JcePEMDecryptorProviderBuilder decryptor = new JcePEMDecryptorProviderBuilder().setProvider(provider); + PEMKeyPair keyPair = ((PEMEncryptedKeyPair) object).decryptKeyPair(decryptor.build(password)); + pkInfo = keyPair.getPrivateKeyInfo(); + } else if (object instanceof PKCS8EncryptedPrivateKeyInfo) { + if (password == null) { + throw new NeedsPasswordException(); + } + JceOpenSSLPKCS8DecryptorProviderBuilder decryptor = new JceOpenSSLPKCS8DecryptorProviderBuilder().setProvider(provider); + pkInfo = ((PKCS8EncryptedPrivateKeyInfo) object).decryptPrivateKeyInfo(decryptor.build(password)); + } else if (object instanceof PrivateKeyInfo) { + pkInfo = (PrivateKeyInfo) object; + } else { + continue; + } + return converter.getPrivateKey(pkInfo); + } + return null; + } catch (OperatorCreationException | PKCSException e) { + throw new GeneralSecurityException(e); + } + } + + @Override + public MessageDigest createDigest(String algorithm) throws NoSuchAlgorithmException { + return MessageDigest.getInstance(algorithm, getProvider()); + } + + @Override + public Signature createSignature(String algorithm) throws NoSuchAlgorithmException { + return Signature.getInstance(algorithm, getProvider()); + } +} diff --git a/graalpython/com.oracle.graal.python.test/src/tests/ssldata/cert_dsa.pem b/graalpython/com.oracle.graal.python.test/src/tests/ssldata/cert_dsa.pem new file mode 100644 index 0000000000..c9a8c010d7 --- /dev/null +++ b/graalpython/com.oracle.graal.python.test/src/tests/ssldata/cert_dsa.pem @@ -0,0 +1,26 @@ +-----BEGIN CERTIFICATE----- +MIIEYzCCBBCgAwIBAgIUa4FezfhUiUvkPAwJQ2GNI7HJNCkwCwYJYIZIAWUDBAMC +MBQxEjAQBgNVBAMMCWxvY2FsaG9zdDAeFw0yNjAzMTYxNjQ4NTBaFw0zNjAzMTMx +NjQ4NTBaMBQxEjAQBgNVBAMMCWxvY2FsaG9zdDCCA0MwggI1BgcqhkjOOAQBMIIC +KAKCAQEAt93WIFjdg9j0JO4MIZzgnzgEQa1CJky7vLfS0S1YetqzE1tyXeWNx/Kj +sxm9OdL8Xvnb5LJKoLJbFZ0yV0/tOqnA1pNn/QH3Fh3p2l9yADu9V6GYcxmwo1U1 +PlZ+oHoj5IFIoQZeENSlPPrTWTj/y0WjGJNwzRlIVTNJpP3vUw5Shf6RmGPq1uJs +RPJRSPiBZ9fccXyffrOpOizrS4HfQpmAsva4/Ijlc1Hn7Ko1uRLMGARpeGmpzxis +tkD4Fns5YH5k21cL3+ZkNlCJAqRZgGwyL+M0WB/LEnk/mlhgt9s0WHLpoxoEPllc +UvPsJ+ZUKPnieijiP0wOMEIF9SvdwwIdANAJ0cXh8PGBvIfV6Wg+3p8Jz64Cz3g7 +McVpzuMCggEAaEER2Jrd9lmlQdDjkH21GaMkiwpNnSExwMwnAjprZe+n+3/9Xv6e +dNJKxK9ITx7xe+CCjfOl3M0m/Spo+hLoL9dLiJ/3ZfxfRkfDizWTxwbh6jDzEfh5 +vW0Xkx1aALRudGH8t6VnlBrSCjj0r6Ih7z3m0eTe/3PV47p9CrD0KLUiKS+GcDYT +rgglG/jLhKEaR22/T2jLP4VaE15Yi6Vc9LcFwQyLrKytDgqsChqaJzAl/72YWzob +tFkCUM94h0Jx7vMTlIwhBihxya4yAiERxZFKENhs1mhMLMu2fCk2K3BChMVm42fE +UFywxOvChj2DOQvYQTOuTNz/yyqONZEuxQOCAQYAAoIBAQCHmjdKyPjTSl5ErgvA +gG4+h1Z5NBty1dgORCB8JK8IkUojAre8nvZvExFSFBjyr5TCvLR6vDvB5sn16+zP +w7QNMDPvLNZ74lBjcnuNXkc9XAuJlj53zSLQy/jvi+Hf1UknAfnfrIXQ/v40Pmz5 +hyhRbLjOiF6azm56DzsFRdoi88cihRnI0pSDaaE09/sPJdZVEmWfLKEbFAQGSo55 +f5aoSOpFzUElFp/OdHAj8InuhxP8QXPFYx5xmUAvc1yyw47Qz9Fp6ewFZoE3LquC +GwuXfhMxFGVbD+f2hQhRHDHfOSMg+W6y3+7ZG5mYq+aRwM10/FA2TRL5efzaBuV7 +baTUo1MwUTAdBgNVHQ4EFgQUIbSBGsQPPVVo0LrkNC1f5viGw0owHwYDVR0jBBgw +FoAUIbSBGsQPPVVo0LrkNC1f5viGw0owDwYDVR0TAQH/BAUwAwEB/zALBglghkgB +ZQMEAwIDQAAwPQIcccMSDglufq9UQP3wfXaqW4GOtP5/Ph3R9q9X2gIdAJRsMoM9 +X6l+d5A6kXV+uaXweaZFnoZ9Mo6+JAI= +-----END CERTIFICATE----- diff --git a/graalpython/com.oracle.graal.python.test/src/tests/ssldata/pk_dsa_legacy.pem b/graalpython/com.oracle.graal.python.test/src/tests/ssldata/pk_dsa_legacy.pem new file mode 100644 index 0000000000..381ccf8c60 --- /dev/null +++ b/graalpython/com.oracle.graal.python.test/src/tests/ssldata/pk_dsa_legacy.pem @@ -0,0 +1,20 @@ +-----BEGIN DSA PRIVATE KEY----- +MIIDTgIBAAKCAQEAt93WIFjdg9j0JO4MIZzgnzgEQa1CJky7vLfS0S1YetqzE1ty +XeWNx/Kjsxm9OdL8Xvnb5LJKoLJbFZ0yV0/tOqnA1pNn/QH3Fh3p2l9yADu9V6GY +cxmwo1U1PlZ+oHoj5IFIoQZeENSlPPrTWTj/y0WjGJNwzRlIVTNJpP3vUw5Shf6R +mGPq1uJsRPJRSPiBZ9fccXyffrOpOizrS4HfQpmAsva4/Ijlc1Hn7Ko1uRLMGARp +eGmpzxistkD4Fns5YH5k21cL3+ZkNlCJAqRZgGwyL+M0WB/LEnk/mlhgt9s0WHLp +oxoEPllcUvPsJ+ZUKPnieijiP0wOMEIF9SvdwwIdANAJ0cXh8PGBvIfV6Wg+3p8J +z64Cz3g7McVpzuMCggEAaEER2Jrd9lmlQdDjkH21GaMkiwpNnSExwMwnAjprZe+n ++3/9Xv6edNJKxK9ITx7xe+CCjfOl3M0m/Spo+hLoL9dLiJ/3ZfxfRkfDizWTxwbh +6jDzEfh5vW0Xkx1aALRudGH8t6VnlBrSCjj0r6Ih7z3m0eTe/3PV47p9CrD0KLUi +KS+GcDYTrgglG/jLhKEaR22/T2jLP4VaE15Yi6Vc9LcFwQyLrKytDgqsChqaJzAl +/72YWzobtFkCUM94h0Jx7vMTlIwhBihxya4yAiERxZFKENhs1mhMLMu2fCk2K3BC +hMVm42fEUFywxOvChj2DOQvYQTOuTNz/yyqONZEuxQKCAQEAh5o3Ssj400peRK4L +wIBuPodWeTQbctXYDkQgfCSvCJFKIwK3vJ72bxMRUhQY8q+Uwry0erw7webJ9evs +z8O0DTAz7yzWe+JQY3J7jV5HPVwLiZY+d80i0Mv474vh39VJJwH536yF0P7+ND5s ++YcoUWy4zohems5ueg87BUXaIvPHIoUZyNKUg2mhNPf7DyXWVRJlnyyhGxQEBkqO +eX+WqEjqRc1BJRafznRwI/CJ7ocT/EFzxWMecZlAL3NcssOO0M/RaensBWaBNy6r +ghsLl34TMRRlWw/n9oUIURwx3zkjIPlust/u2RuZmKvmkcDNdPxQNk0S+Xn82gbl +e22k1AIcANOj4eSn45Oi3o7NSpqU/LZ0PYo5tD1osrjZTA== +-----END DSA PRIVATE KEY----- diff --git a/graalpython/com.oracle.graal.python.test/src/tests/ssldata/pk_ecc_legacy.pem b/graalpython/com.oracle.graal.python.test/src/tests/ssldata/pk_ecc_legacy.pem new file mode 100644 index 0000000000..580e5ef888 --- /dev/null +++ b/graalpython/com.oracle.graal.python.test/src/tests/ssldata/pk_ecc_legacy.pem @@ -0,0 +1,6 @@ +-----BEGIN EC PRIVATE KEY----- +MIGkAgEBBDBL2Y5JfpzbgHw+t4Q+c5SHhsZcD9ylEtUMg7OyF9xW6j+3VIVORGao +kcOtE0Z2Y5egBwYFK4EEACKhZANiAASzz/rInKUzonpxP5bLxmq8fmrtgRSS0jRP +UOU16XKX+KtifnLbmLHQtPrctdkRRROCxnURz2fBihQTJkXyBMSswNTRCs+4DUKb +MAfihigMVYgdWbZPFBDleo5aeFw4/FM= +-----END EC PRIVATE KEY----- diff --git a/graalpython/com.oracle.graal.python.test/src/tests/test_imports.py b/graalpython/com.oracle.graal.python.test/src/tests/test_imports.py index fd5420b03d..dc7bd6d7eb 100644 --- a/graalpython/com.oracle.graal.python.test/src/tests/test_imports.py +++ b/graalpython/com.oracle.graal.python.test/src/tests/test_imports.py @@ -1,4 +1,4 @@ -# Copyright (c) 2018, 2024, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2018, 2026, Oracle and/or its affiliates. All rights reserved. # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. # # The Universal Permissive License (UPL), Version 1.0 @@ -146,6 +146,11 @@ def func(x): assert code.co_filename == old_name + '_more_path' +def test_imp_source_hash(): + import _imp + assert _imp.source_hash(123456789, b'hello!').hex() == '04e61e229a23a446' + + def test_recursive_import_from(): if sys.version_info.minor >= 6: import package.recpkg @@ -176,16 +181,16 @@ def test_circular_import_valid(): import time as package25274 #has to be in global space for the next test def test_local_property_25274(): - + def mytest(): assert len(locals()) == 0 import package25274.sub25274 assert 'package25274' in locals() assert package25274.top_property == 10 assert package25274.sub25274.sub_property == 20 - + mytest() assert hasattr(package25274, 'tzname') - + diff --git a/graalpython/com.oracle.graal.python.test/src/tests/test_ssl.py b/graalpython/com.oracle.graal.python.test/src/tests/test_ssl.py index 1a701cb126..f39f880ed5 100644 --- a/graalpython/com.oracle.graal.python.test/src/tests/test_ssl.py +++ b/graalpython/com.oracle.graal.python.test/src/tests/test_ssl.py @@ -1,4 +1,4 @@ -# Copyright (c) 2021, 2022, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2021, 2026, Oracle and/or its affiliates. All rights reserved. # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. # # The Universal Permissive License (UPL), Version 1.0 @@ -372,6 +372,18 @@ def test_private_key_pkcs1(self): def test_private_key_pkcs1_password(self): self.check_keypair("signed_cert_pkcs1_password.pem", "signing_ca.pem", password="password") + def test_private_key_ec_legacy(self): + server_context = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER) + server_context.load_cert_chain(data_file("keycertecc.pem"), keyfile=data_file("pk_ecc_legacy.pem")) + client_context = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT) + client_context.check_hostname = False + client_context.verify_mode = ssl.CERT_NONE + check_handshake(server_context, client_context) + + def test_private_key_dsa_legacy(self): + server_context = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER) + server_context.load_cert_chain(data_file("cert_dsa.pem"), keyfile=data_file("pk_dsa_legacy.pem")) + def test_alpn(self): signed_cert = data_file("signed_cert.pem") server_context = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER) @@ -426,3 +438,7 @@ def test_error(self): get_cipher_list("ALL:!ALL:ADH") with self.assertRaisesRegex(ssl.SSLError, "No cipher can be selected"): get_cipher_list("ALL:@XXX") + import sys + if sys.implementation.name == "graalpy": + with self.assertRaisesRegex(NotImplementedError, "only @SECLEVEL=1 is supported"): + get_cipher_list("@SECLEVEL=2:ALL") diff --git a/graalpython/com.oracle.graal.python/src/META-INF/native-image/org.graalvm.python/python-language/native-image.properties b/graalpython/com.oracle.graal.python/src/META-INF/native-image/org.graalvm.python/python-language/native-image.properties index 5a301fcffd..a06ea7e9d1 100644 --- a/graalpython/com.oracle.graal.python/src/META-INF/native-image/org.graalvm.python/python-language/native-image.properties +++ b/graalpython/com.oracle.graal.python/src/META-INF/native-image/org.graalvm.python/python-language/native-image.properties @@ -1,6 +1,6 @@ # This file contains native-image arguments needed to build graalpython Args = -H:MaxRuntimeCompileMethods=20000 \ --initialize-at-build-time=com.oracle.graal.python,com.oracle.truffle.regex \ - --features=com.oracle.graal.python.BouncyCastleFeature \ --add-exports=org.graalvm.nativeimage/org.graalvm.nativeimage.impl=org.graalvm.py \ - --add-exports=org.graalvm.nativeimage/org.graalvm.nativeimage.impl=ALL-UNNAMED + --add-exports=org.graalvm.nativeimage/org.graalvm.nativeimage.impl=ALL-UNNAMED \ + --features=com.oracle.graal.python.runtime.PythonCryptoFeature diff --git a/graalpython/com.oracle.graal.python/src/META-INF/native-image/org.graalvm.python/python-language/reflect-config.json b/graalpython/com.oracle.graal.python/src/META-INF/native-image/org.graalvm.python/python-language/reflect-config.json index 01c0e6128f..83f2445116 100644 --- a/graalpython/com.oracle.graal.python/src/META-INF/native-image/org.graalvm.python/python-language/reflect-config.json +++ b/graalpython/com.oracle.graal.python/src/META-INF/native-image/org.graalvm.python/python-language/reflect-config.json @@ -81,2194 +81,136 @@ "name": "", "parameterTypes": [] } - ], - "condition": { - "typeReachable": "org.bouncycastle.jce.provider.BouncyCastleProvider" - } - }, - { - "name": "com.sun.crypto.provider.AESKeyGenerator", - "methods": [ - { - "name": "", - "parameterTypes": [] - } - ], - "condition": { - "typeReachable": "org.bouncycastle.jce.provider.BouncyCastleProvider" - } - }, - { - "name": "com.sun.crypto.provider.ARCFOURCipher", - "methods": [ - { - "name": "", - "parameterTypes": [] - } - ], - "condition": { - "typeReachable": "org.bouncycastle.jce.provider.BouncyCastleProvider" - } - }, - { - "name": "com.sun.crypto.provider.ChaCha20Cipher$ChaCha20Poly1305", - "methods": [ - { - "name": "", - "parameterTypes": [] - } - ], - "condition": { - "typeReachable": "org.bouncycastle.jce.provider.BouncyCastleProvider" - } - }, - { - "name": "com.sun.crypto.provider.DESCipher", - "methods": [ - { - "name": "", - "parameterTypes": [] - } - ], - "condition": { - "typeReachable": "org.bouncycastle.jce.provider.BouncyCastleProvider" - } - }, - { - "name": "com.sun.crypto.provider.DESedeCipher", - "methods": [ - { - "name": "", - "parameterTypes": [] - } - ], - "condition": { - "typeReachable": "org.bouncycastle.jce.provider.BouncyCastleProvider" - } - }, - { - "name": "com.sun.crypto.provider.DHParameters", - "methods": [ - { - "name": "", - "parameterTypes": [] - } - ], - "condition": { - "typeReachable": "org.bouncycastle.jce.provider.BouncyCastleProvider" - } - }, - { - "name": "com.sun.crypto.provider.GaloisCounterMode$AESGCM", - "methods": [ - { - "name": "", - "parameterTypes": [] - } - ], - "condition": { - "typeReachable": "org.bouncycastle.jce.provider.BouncyCastleProvider" - } - }, - { - "name": "com.sun.crypto.provider.HmacCore$HmacSHA384", - "methods": [ - { - "name": "", - "parameterTypes": [] - } - ], - "condition": { - "typeReachable": "org.bouncycastle.jce.provider.BouncyCastleProvider" - } - }, - { - "name": "com.sun.crypto.provider.TlsKeyMaterialGenerator", - "methods": [ - { - "name": "", - "parameterTypes": [] - } - ], - "condition": { - "typeReachable": "org.bouncycastle.jce.provider.BouncyCastleProvider" - } - }, - { - "name": "com.sun.crypto.provider.TlsMasterSecretGenerator", - "methods": [ - { - "name": "", - "parameterTypes": [] - } - ], - "condition": { - "typeReachable": "org.bouncycastle.jce.provider.BouncyCastleProvider" - } - }, - { - "name": "com.sun.crypto.provider.TlsPrfGenerator$V12", - "methods": [ - { - "name": "", - "parameterTypes": [] - } - ], - "condition": { - "typeReachable": "org.bouncycastle.jce.provider.BouncyCastleProvider" - } - }, - { - "name": "java.security.KeyStoreSpi", - "condition": { - "typeReachable": "org.bouncycastle.jce.provider.BouncyCastleProvider" - } - }, - { - "name": "java.security.cert.PKIXRevocationChecker", - "condition": { - "typeReachable": "org.bouncycastle.jce.provider.BouncyCastleProvider" - } - }, - { - "name": "java.security.interfaces.DSAPrivateKey", - "condition": { - "typeReachable": "org.bouncycastle.jce.provider.BouncyCastleProvider" - } - }, - { - "name": "java.security.interfaces.DSAPublicKey", - "condition": { - "typeReachable": "org.bouncycastle.jce.provider.BouncyCastleProvider" - } - }, - { - "name": "java.security.interfaces.ECPrivateKey", - "condition": { - "typeReachable": "org.bouncycastle.jce.provider.BouncyCastleProvider" - } - }, - { - "name": "java.security.interfaces.ECPublicKey", - "condition": { - "typeReachable": "org.bouncycastle.jce.provider.BouncyCastleProvider" - } - }, - { - "name": "java.security.interfaces.RSAPrivateKey", - "condition": { - "typeReachable": "org.bouncycastle.jce.provider.BouncyCastleProvider" - } - }, - { - "name": "java.security.interfaces.RSAPublicKey", - "condition": { - "typeReachable": "org.bouncycastle.jce.provider.BouncyCastleProvider" - } - }, - { - "name": "java.security.spec.DSAParameterSpec", - "condition": { - "typeReachable": "org.bouncycastle.jce.provider.BouncyCastleProvider" - } - }, - { - "name": "javax.crypto.spec.GCMParameterSpec", - "condition": { - "typeReachable": "org.bouncycastle.jce.provider.BouncyCastleProvider" - } - }, - { - "name": "org.bouncycastle.jcajce.provider.asymmetric.COMPOSITE$Mappings", - "methods": [ - { - "name": "", - "parameterTypes": [] - } - ], - "condition": { - "typeReachable": "org.bouncycastle.jce.provider.BouncyCastleProvider" - } - }, - { - "name": "org.bouncycastle.jcajce.provider.asymmetric.CompositeSignatures$Mappings", - "methods": [ - { - "name": "", - "parameterTypes": [] - } - ], - "condition": { - "typeReachable": "org.bouncycastle.jce.provider.BouncyCastleProvider" - } - }, - { - "name": "org.bouncycastle.jcajce.provider.asymmetric.DH$Mappings", - "methods": [ - { - "name": "", - "parameterTypes": [] - } - ], - "condition": { - "typeReachable": "org.bouncycastle.jce.provider.BouncyCastleProvider" - } - }, - { - "name": "org.bouncycastle.jcajce.provider.asymmetric.DSA$Mappings", - "methods": [ - { - "name": "", - "parameterTypes": [] - } - ], - "condition": { - "typeReachable": "org.bouncycastle.jce.provider.BouncyCastleProvider" - } - }, - { - "name": "org.bouncycastle.jcajce.provider.asymmetric.DSTU4145$Mappings", - "methods": [ - { - "name": "", - "parameterTypes": [] - } - ], - "condition": { - "typeReachable": "org.bouncycastle.jce.provider.BouncyCastleProvider" - } - }, - { - "name": "org.bouncycastle.jcajce.provider.asymmetric.Dilithium$Mappings", - "methods": [ - { - "name": "", - "parameterTypes": [] - } - ], - "condition": { - "typeReachable": "org.bouncycastle.jce.provider.BouncyCastleProvider" - } - }, - { - "name": "org.bouncycastle.jcajce.provider.asymmetric.EC$Mappings", - "methods": [ - { - "name": "", - "parameterTypes": [] - } - ], - "condition": { - "typeReachable": "org.bouncycastle.jce.provider.BouncyCastleProvider" - } - }, - { - "name": "org.bouncycastle.jcajce.provider.asymmetric.ECGOST$Mappings", - "methods": [ - { - "name": "", - "parameterTypes": [] - } - ], - "condition": { - "typeReachable": "org.bouncycastle.jce.provider.BouncyCastleProvider" - } - }, - { - "name": "org.bouncycastle.jcajce.provider.asymmetric.EXTERNAL$Mappings", - "methods": [ - { - "name": "", - "parameterTypes": [] - } - ], - "condition": { - "typeReachable": "org.bouncycastle.jce.provider.BouncyCastleProvider" - } - }, - { - "name": "org.bouncycastle.jcajce.provider.asymmetric.EdEC$Mappings", - "methods": [ - { - "name": "", - "parameterTypes": [] - } - ], - "condition": { - "typeReachable": "org.bouncycastle.jce.provider.BouncyCastleProvider" - } - }, - { - "name": "org.bouncycastle.jcajce.provider.asymmetric.ElGamal$Mappings", - "methods": [ - { - "name": "", - "parameterTypes": [] - } - ], - "condition": { - "typeReachable": "org.bouncycastle.jce.provider.BouncyCastleProvider" - } - }, - { - "name": "org.bouncycastle.jcajce.provider.asymmetric.Falcon$Mappings", - "methods": [ - { - "name": "", - "parameterTypes": [] - } - ], - "condition": { - "typeReachable": "org.bouncycastle.jce.provider.BouncyCastleProvider" - } - }, - { - "name": "org.bouncycastle.jcajce.provider.asymmetric.GM$Mappings", - "methods": [ - { - "name": "", - "parameterTypes": [] - } - ], - "condition": { - "typeReachable": "org.bouncycastle.jce.provider.BouncyCastleProvider" - } - }, - { - "name": "org.bouncycastle.jcajce.provider.asymmetric.GOST$Mappings", - "methods": [ - { - "name": "", - "parameterTypes": [] - } - ], - "condition": { - "typeReachable": "org.bouncycastle.jce.provider.BouncyCastleProvider" - } - }, - { - "name": "org.bouncycastle.jcajce.provider.asymmetric.IES$Mappings", - "methods": [ - { - "name": "", - "parameterTypes": [] - } - ], - "condition": { - "typeReachable": "org.bouncycastle.jce.provider.BouncyCastleProvider" - } - }, - { - "name": "org.bouncycastle.jcajce.provider.asymmetric.LMS$Mappings", - "methods": [ - { - "name": "", - "parameterTypes": [] - } - ], - "condition": { - "typeReachable": "org.bouncycastle.jce.provider.BouncyCastleProvider" - } - }, - { - "name": "org.bouncycastle.jcajce.provider.asymmetric.NTRU$Mappings", - "methods": [ - { - "name": "", - "parameterTypes": [] - } - ], - "condition": { - "typeReachable": "org.bouncycastle.jce.provider.BouncyCastleProvider" - } - }, - { - "name": "org.bouncycastle.jcajce.provider.asymmetric.RSA$Mappings", - "methods": [ - { - "name": "", - "parameterTypes": [] - } - ], - "condition": { - "typeReachable": "org.bouncycastle.jce.provider.BouncyCastleProvider" - } - }, - { - "name": "org.bouncycastle.jcajce.provider.asymmetric.SPHINCSPlus$Mappings", - "methods": [ - { - "name": "", - "parameterTypes": [] - } - ], - "condition": { - "typeReachable": "org.bouncycastle.jce.provider.BouncyCastleProvider" - } - }, - { - "name": "org.bouncycastle.jcajce.provider.asymmetric.X509$Mappings", - "methods": [ - { - "name": "", - "parameterTypes": [] - } - ], - "condition": { - "typeReachable": "org.bouncycastle.jce.provider.BouncyCastleProvider" - } - }, - { - "name": "org.bouncycastle.jcajce.provider.asymmetric.ec.KeyFactorySpi$ECDSA", - "methods": [ - { - "name": "", - "parameterTypes": [] - } - ], - "condition": { - "typeReachable": "org.bouncycastle.jce.provider.BouncyCastleProvider" - } - }, - { - "name": "org.bouncycastle.jcajce.provider.asymmetric.ec.SignatureSpi$ecDSA256", - "methods": [ - { - "name": "", - "parameterTypes": [] - } - ], - "condition": { - "typeReachable": "org.bouncycastle.jce.provider.BouncyCastleProvider" - } - }, - { - "name": "org.bouncycastle.jcajce.provider.asymmetric.rsa.KeyFactorySpi", - "methods": [ - { - "name": "", - "parameterTypes": [] - } - ], - "condition": { - "typeReachable": "org.bouncycastle.jce.provider.BouncyCastleProvider" - } - }, - { - "name": "org.bouncycastle.jcajce.provider.digest.Blake2b$Blake2b160", - "methods": [ - { - "name": "", - "parameterTypes": [] - } - ], - "condition": { - "typeReachable": "org.bouncycastle.jce.provider.BouncyCastleProvider" - } - }, - { - "name": "org.bouncycastle.jcajce.provider.digest.Blake2b$Blake2b256", - "methods": [ - { - "name": "", - "parameterTypes": [] - } - ], - "condition": { - "typeReachable": "org.bouncycastle.jce.provider.BouncyCastleProvider" - } - }, - { - "name": "org.bouncycastle.jcajce.provider.digest.Blake2b$Blake2b384", - "methods": [ - { - "name": "", - "parameterTypes": [] - } - ], - "condition": { - "typeReachable": "org.bouncycastle.jce.provider.BouncyCastleProvider" - } - }, - { - "name": "org.bouncycastle.jcajce.provider.digest.Blake2b$Blake2b512", - "methods": [ - { - "name": "", - "parameterTypes": [] - } - ], - "condition": { - "typeReachable": "org.bouncycastle.jce.provider.BouncyCastleProvider" - } - }, - { - "name": "org.bouncycastle.jcajce.provider.digest.Blake2b$Mappings", - "methods": [ - { - "name": "", - "parameterTypes": [] - } - ], - "condition": { - "typeReachable": "org.bouncycastle.jce.provider.BouncyCastleProvider" - } - }, - { - "name": "org.bouncycastle.jcajce.provider.digest.Blake2s$Blake2s128", - "methods": [ - { - "name": "", - "parameterTypes": [] - } - ], - "condition": { - "typeReachable": "org.bouncycastle.jce.provider.BouncyCastleProvider" - } - }, - { - "name": "org.bouncycastle.jcajce.provider.digest.Blake2s$Blake2s160", - "methods": [ - { - "name": "", - "parameterTypes": [] - } - ], - "condition": { - "typeReachable": "org.bouncycastle.jce.provider.BouncyCastleProvider" - } - }, - { - "name": "org.bouncycastle.jcajce.provider.digest.Blake2s$Blake2s224", - "methods": [ - { - "name": "", - "parameterTypes": [] - } - ], - "condition": { - "typeReachable": "org.bouncycastle.jce.provider.BouncyCastleProvider" - } - }, - { - "name": "org.bouncycastle.jcajce.provider.digest.Blake2s$Blake2s256", - "methods": [ - { - "name": "", - "parameterTypes": [] - } - ], - "condition": { - "typeReachable": "org.bouncycastle.jce.provider.BouncyCastleProvider" - } - }, - { - "name": "org.bouncycastle.jcajce.provider.digest.Blake2s$Mappings", - "methods": [ - { - "name": "", - "parameterTypes": [] - } - ], - "condition": { - "typeReachable": "org.bouncycastle.jce.provider.BouncyCastleProvider" - } - }, - { - "name": "org.bouncycastle.jcajce.provider.digest.Blake3$Blake3_256", - "methods": [ - { - "name": "", - "parameterTypes": [] - } - ], - "condition": { - "typeReachable": "org.bouncycastle.jce.provider.BouncyCastleProvider" - } - }, - { - "name": "org.bouncycastle.jcajce.provider.digest.Blake3$Mappings", - "methods": [ - { - "name": "", - "parameterTypes": [] - } - ], - "condition": { - "typeReachable": "org.bouncycastle.jce.provider.BouncyCastleProvider" - } - }, - { - "name": "org.bouncycastle.jcajce.provider.digest.DSTU7564$Digest256", - "methods": [ - { - "name": "", - "parameterTypes": [] - } - ], - "condition": { - "typeReachable": "org.bouncycastle.jce.provider.BouncyCastleProvider" - } - }, - { - "name": "org.bouncycastle.jcajce.provider.digest.DSTU7564$Digest384", - "methods": [ - { - "name": "", - "parameterTypes": [] - } - ], - "condition": { - "typeReachable": "org.bouncycastle.jce.provider.BouncyCastleProvider" - } - }, - { - "name": "org.bouncycastle.jcajce.provider.digest.DSTU7564$Digest512", - "methods": [ - { - "name": "", - "parameterTypes": [] - } - ], - "condition": { - "typeReachable": "org.bouncycastle.jce.provider.BouncyCastleProvider" - } - }, - { - "name": "org.bouncycastle.jcajce.provider.digest.DSTU7564$Mappings", - "methods": [ - { - "name": "", - "parameterTypes": [] - } - ], - "condition": { - "typeReachable": "org.bouncycastle.jce.provider.BouncyCastleProvider" - } - }, - { - "name": "org.bouncycastle.jcajce.provider.digest.GOST3411$Digest", - "methods": [ - { - "name": "", - "parameterTypes": [] - } - ], - "condition": { - "typeReachable": "org.bouncycastle.jce.provider.BouncyCastleProvider" - } - }, - { - "name": "org.bouncycastle.jcajce.provider.digest.GOST3411$Digest2012_256", - "methods": [ - { - "name": "", - "parameterTypes": [] - } - ], - "condition": { - "typeReachable": "org.bouncycastle.jce.provider.BouncyCastleProvider" - } - }, - { - "name": "org.bouncycastle.jcajce.provider.digest.GOST3411$Digest2012_512", - "methods": [ - { - "name": "", - "parameterTypes": [] - } - ], - "condition": { - "typeReachable": "org.bouncycastle.jce.provider.BouncyCastleProvider" - } - }, - { - "name": "org.bouncycastle.jcajce.provider.digest.GOST3411$Mappings", - "methods": [ - { - "name": "", - "parameterTypes": [] - } - ], - "condition": { - "typeReachable": "org.bouncycastle.jce.provider.BouncyCastleProvider" - } - }, - { - "name": "org.bouncycastle.jcajce.provider.digest.Haraka$Digest256", - "methods": [ - { - "name": "", - "parameterTypes": [] - } - ], - "condition": { - "typeReachable": "org.bouncycastle.jce.provider.BouncyCastleProvider" - } - }, - { - "name": "org.bouncycastle.jcajce.provider.digest.Haraka$Digest512", - "methods": [ - { - "name": "", - "parameterTypes": [] - } - ], - "condition": { - "typeReachable": "org.bouncycastle.jce.provider.BouncyCastleProvider" - } - }, - { - "name": "org.bouncycastle.jcajce.provider.digest.Haraka$Mappings", - "methods": [ - { - "name": "", - "parameterTypes": [] - } - ], - "condition": { - "typeReachable": "org.bouncycastle.jce.provider.BouncyCastleProvider" - } - }, - { - "name": "org.bouncycastle.jcajce.provider.digest.Keccak$Digest224", - "methods": [ - { - "name": "", - "parameterTypes": [] - } - ], - "condition": { - "typeReachable": "org.bouncycastle.jce.provider.BouncyCastleProvider" - } - }, - { - "name": "org.bouncycastle.jcajce.provider.digest.Keccak$Digest256", - "methods": [ - { - "name": "", - "parameterTypes": [] - } - ], - "condition": { - "typeReachable": "org.bouncycastle.jce.provider.BouncyCastleProvider" - } - }, - { - "name": "org.bouncycastle.jcajce.provider.digest.Keccak$Digest288", - "methods": [ - { - "name": "", - "parameterTypes": [] - } - ], - "condition": { - "typeReachable": "org.bouncycastle.jce.provider.BouncyCastleProvider" - } - }, - { - "name": "org.bouncycastle.jcajce.provider.digest.Keccak$Digest384", - "methods": [ - { - "name": "", - "parameterTypes": [] - } - ], - "condition": { - "typeReachable": "org.bouncycastle.jce.provider.BouncyCastleProvider" - } - }, - { - "name": "org.bouncycastle.jcajce.provider.digest.Keccak$Digest512", - "methods": [ - { - "name": "", - "parameterTypes": [] - } - ], - "condition": { - "typeReachable": "org.bouncycastle.jce.provider.BouncyCastleProvider" - } - }, - { - "name": "org.bouncycastle.jcajce.provider.digest.Keccak$Mappings", - "methods": [ - { - "name": "", - "parameterTypes": [] - } - ], - "condition": { - "typeReachable": "org.bouncycastle.jce.provider.BouncyCastleProvider" - } - }, - { - "name": "org.bouncycastle.jcajce.provider.digest.MD2$Mappings", - "methods": [ - { - "name": "", - "parameterTypes": [] - } - ], - "condition": { - "typeReachable": "org.bouncycastle.jce.provider.BouncyCastleProvider" - } - }, - { - "name": "org.bouncycastle.jcajce.provider.digest.MD4$Digest", - "methods": [ - { - "name": "", - "parameterTypes": [] - } - ], - "condition": { - "typeReachable": "org.bouncycastle.jce.provider.BouncyCastleProvider" - } - }, - { - "name": "org.bouncycastle.jcajce.provider.digest.MD4$Mappings", - "methods": [ - { - "name": "", - "parameterTypes": [] - } - ], - "condition": { - "typeReachable": "org.bouncycastle.jce.provider.BouncyCastleProvider" - } - }, - { - "name": "org.bouncycastle.jcajce.provider.digest.MD5$Mappings", - "methods": [ - { - "name": "", - "parameterTypes": [] - } - ], - "condition": { - "typeReachable": "org.bouncycastle.jce.provider.BouncyCastleProvider" - } - }, - { - "name": "org.bouncycastle.jcajce.provider.digest.RIPEMD128$Digest", - "methods": [ - { - "name": "", - "parameterTypes": [] - } - ], - "condition": { - "typeReachable": "org.bouncycastle.jce.provider.BouncyCastleProvider" - } - }, - { - "name": "org.bouncycastle.jcajce.provider.digest.RIPEMD128$Mappings", - "methods": [ - { - "name": "", - "parameterTypes": [] - } - ], - "condition": { - "typeReachable": "org.bouncycastle.jce.provider.BouncyCastleProvider" - } - }, - { - "name": "org.bouncycastle.jcajce.provider.digest.RIPEMD160$Digest", - "methods": [ - { - "name": "", - "parameterTypes": [] - } - ], - "condition": { - "typeReachable": "org.bouncycastle.jce.provider.BouncyCastleProvider" - } - }, - { - "name": "org.bouncycastle.jcajce.provider.digest.RIPEMD160$Mappings", - "methods": [ - { - "name": "", - "parameterTypes": [] - } - ], - "condition": { - "typeReachable": "org.bouncycastle.jce.provider.BouncyCastleProvider" - } - }, - { - "name": "org.bouncycastle.jcajce.provider.digest.RIPEMD256$Digest", - "methods": [ - { - "name": "", - "parameterTypes": [] - } - ], - "condition": { - "typeReachable": "org.bouncycastle.jce.provider.BouncyCastleProvider" - } - }, - { - "name": "org.bouncycastle.jcajce.provider.digest.RIPEMD256$Mappings", - "methods": [ - { - "name": "", - "parameterTypes": [] - } - ], - "condition": { - "typeReachable": "org.bouncycastle.jce.provider.BouncyCastleProvider" - } - }, - { - "name": "org.bouncycastle.jcajce.provider.digest.RIPEMD320$Digest", - "methods": [ - { - "name": "", - "parameterTypes": [] - } - ], - "condition": { - "typeReachable": "org.bouncycastle.jce.provider.BouncyCastleProvider" - } - }, - { - "name": "org.bouncycastle.jcajce.provider.digest.RIPEMD320$Mappings", - "methods": [ - { - "name": "", - "parameterTypes": [] - } - ], - "condition": { - "typeReachable": "org.bouncycastle.jce.provider.BouncyCastleProvider" - } - }, - { - "name": "org.bouncycastle.jcajce.provider.digest.SHA1$Mappings", - "methods": [ - { - "name": "", - "parameterTypes": [] - } - ], - "condition": { - "typeReachable": "org.bouncycastle.jce.provider.BouncyCastleProvider" - } - }, - { - "name": "org.bouncycastle.jcajce.provider.digest.SHA224$Mappings", - "methods": [ - { - "name": "", - "parameterTypes": [] - } - ], - "condition": { - "typeReachable": "org.bouncycastle.jce.provider.BouncyCastleProvider" - } - }, - { - "name": "org.bouncycastle.jcajce.provider.digest.SHA256$Mappings", - "methods": [ - { - "name": "", - "parameterTypes": [] - } - ], - "condition": { - "typeReachable": "org.bouncycastle.jce.provider.BouncyCastleProvider" - } - }, - { - "name": "org.bouncycastle.jcajce.provider.digest.SHA3$DigestParallelHash128_256", - "methods": [ - { - "name": "", - "parameterTypes": [] - } - ], - "condition": { - "typeReachable": "org.bouncycastle.jce.provider.BouncyCastleProvider" - } - }, - { - "name": "org.bouncycastle.jcajce.provider.digest.SHA3$DigestParallelHash256_512", - "methods": [ - { - "name": "", - "parameterTypes": [] - } - ], - "condition": { - "typeReachable": "org.bouncycastle.jce.provider.BouncyCastleProvider" - } - }, - { - "name": "org.bouncycastle.jcajce.provider.digest.SHA3$DigestShake128_256", - "methods": [ - { - "name": "", - "parameterTypes": [] - } - ], - "condition": { - "typeReachable": "org.bouncycastle.jce.provider.BouncyCastleProvider" - } - }, - { - "name": "org.bouncycastle.jcajce.provider.digest.SHA3$DigestShake256_512", - "methods": [ - { - "name": "", - "parameterTypes": [] - } - ], - "condition": { - "typeReachable": "org.bouncycastle.jce.provider.BouncyCastleProvider" - } - }, - { - "name": "org.bouncycastle.jcajce.provider.digest.SHA3$DigestTupleHash128_256", - "methods": [ - { - "name": "", - "parameterTypes": [] - } - ], - "condition": { - "typeReachable": "org.bouncycastle.jce.provider.BouncyCastleProvider" - } - }, - { - "name": "org.bouncycastle.jcajce.provider.digest.SHA3$DigestTupleHash256_512", - "methods": [ - { - "name": "", - "parameterTypes": [] - } - ], - "condition": { - "typeReachable": "org.bouncycastle.jce.provider.BouncyCastleProvider" - } - }, - { - "name": "org.bouncycastle.jcajce.provider.digest.SHA3$Mappings", - "methods": [ - { - "name": "", - "parameterTypes": [] - } - ], - "condition": { - "typeReachable": "org.bouncycastle.jce.provider.BouncyCastleProvider" - } - }, - { - "name": "org.bouncycastle.jcajce.provider.digest.SHA384$Mappings", - "methods": [ - { - "name": "", - "parameterTypes": [] - } - ], - "condition": { - "typeReachable": "org.bouncycastle.jce.provider.BouncyCastleProvider" - } - }, - { - "name": "org.bouncycastle.jcajce.provider.digest.SHA512$Mappings", - "methods": [ - { - "name": "", - "parameterTypes": [] - } - ], - "condition": { - "typeReachable": "org.bouncycastle.jce.provider.BouncyCastleProvider" - } - }, - { - "name": "org.bouncycastle.jcajce.provider.digest.SM3$Digest", - "methods": [ - { - "name": "", - "parameterTypes": [] - } - ], - "condition": { - "typeReachable": "org.bouncycastle.jce.provider.BouncyCastleProvider" - } - }, - { - "name": "org.bouncycastle.jcajce.provider.digest.SM3$Mappings", - "methods": [ - { - "name": "", - "parameterTypes": [] - } - ], - "condition": { - "typeReachable": "org.bouncycastle.jce.provider.BouncyCastleProvider" - } - }, - { - "name": "org.bouncycastle.jcajce.provider.digest.Skein$Digest_1024_1024", - "methods": [ - { - "name": "", - "parameterTypes": [] - } - ], - "condition": { - "typeReachable": "org.bouncycastle.jce.provider.BouncyCastleProvider" - } - }, - { - "name": "org.bouncycastle.jcajce.provider.digest.Skein$Digest_1024_384", - "methods": [ - { - "name": "", - "parameterTypes": [] - } - ], - "condition": { - "typeReachable": "org.bouncycastle.jce.provider.BouncyCastleProvider" - } - }, - { - "name": "org.bouncycastle.jcajce.provider.digest.Skein$Digest_1024_512", - "methods": [ - { - "name": "", - "parameterTypes": [] - } - ], - "condition": { - "typeReachable": "org.bouncycastle.jce.provider.BouncyCastleProvider" - } - }, - { - "name": "org.bouncycastle.jcajce.provider.digest.Skein$Digest_256_128", - "methods": [ - { - "name": "", - "parameterTypes": [] - } - ], - "condition": { - "typeReachable": "org.bouncycastle.jce.provider.BouncyCastleProvider" - } - }, - { - "name": "org.bouncycastle.jcajce.provider.digest.Skein$Digest_256_160", - "methods": [ - { - "name": "", - "parameterTypes": [] - } - ], - "condition": { - "typeReachable": "org.bouncycastle.jce.provider.BouncyCastleProvider" - } - }, - { - "name": "org.bouncycastle.jcajce.provider.digest.Skein$Digest_256_224", - "methods": [ - { - "name": "", - "parameterTypes": [] - } - ], - "condition": { - "typeReachable": "org.bouncycastle.jce.provider.BouncyCastleProvider" - } - }, - { - "name": "org.bouncycastle.jcajce.provider.digest.Skein$Digest_256_256", - "methods": [ - { - "name": "", - "parameterTypes": [] - } - ], - "condition": { - "typeReachable": "org.bouncycastle.jce.provider.BouncyCastleProvider" - } - }, - { - "name": "org.bouncycastle.jcajce.provider.digest.Skein$Digest_512_128", - "methods": [ - { - "name": "", - "parameterTypes": [] - } - ], - "condition": { - "typeReachable": "org.bouncycastle.jce.provider.BouncyCastleProvider" - } - }, - { - "name": "org.bouncycastle.jcajce.provider.digest.Skein$Digest_512_160", - "methods": [ - { - "name": "", - "parameterTypes": [] - } - ], - "condition": { - "typeReachable": "org.bouncycastle.jce.provider.BouncyCastleProvider" - } - }, - { - "name": "org.bouncycastle.jcajce.provider.digest.Skein$Digest_512_224", - "methods": [ - { - "name": "", - "parameterTypes": [] - } - ], - "condition": { - "typeReachable": "org.bouncycastle.jce.provider.BouncyCastleProvider" - } - }, - { - "name": "org.bouncycastle.jcajce.provider.digest.Skein$Digest_512_256", - "methods": [ - { - "name": "", - "parameterTypes": [] - } - ], - "condition": { - "typeReachable": "org.bouncycastle.jce.provider.BouncyCastleProvider" - } - }, - { - "name": "org.bouncycastle.jcajce.provider.digest.Skein$Digest_512_384", - "methods": [ - { - "name": "", - "parameterTypes": [] - } - ], - "condition": { - "typeReachable": "org.bouncycastle.jce.provider.BouncyCastleProvider" - } - }, - { - "name": "org.bouncycastle.jcajce.provider.digest.Skein$Digest_512_512", - "methods": [ - { - "name": "", - "parameterTypes": [] - } - ], - "condition": { - "typeReachable": "org.bouncycastle.jce.provider.BouncyCastleProvider" - } - }, - { - "name": "org.bouncycastle.jcajce.provider.digest.Skein$Mappings", - "methods": [ - { - "name": "", - "parameterTypes": [] - } - ], - "condition": { - "typeReachable": "org.bouncycastle.jce.provider.BouncyCastleProvider" - } - }, - { - "name": "org.bouncycastle.jcajce.provider.digest.Tiger$Digest", - "methods": [ - { - "name": "", - "parameterTypes": [] - } - ], - "condition": { - "typeReachable": "org.bouncycastle.jce.provider.BouncyCastleProvider" - } - }, - { - "name": "org.bouncycastle.jcajce.provider.digest.Tiger$Mappings", - "methods": [ - { - "name": "", - "parameterTypes": [] - } - ], - "condition": { - "typeReachable": "org.bouncycastle.jce.provider.BouncyCastleProvider" - } - }, - { - "name": "org.bouncycastle.jcajce.provider.digest.Whirlpool$Digest", - "methods": [ - { - "name": "", - "parameterTypes": [] - } - ], - "condition": { - "typeReachable": "org.bouncycastle.jce.provider.BouncyCastleProvider" - } - }, - { - "name": "org.bouncycastle.jcajce.provider.digest.Whirlpool$Mappings", - "methods": [ - { - "name": "", - "parameterTypes": [] - } - ], - "condition": { - "typeReachable": "org.bouncycastle.jce.provider.BouncyCastleProvider" - } - }, - { - "name": "org.bouncycastle.jcajce.provider.drbg.DRBG$Mappings", - "methods": [ - { - "name": "", - "parameterTypes": [] - } - ], - "condition": { - "typeReachable": "org.bouncycastle.jce.provider.BouncyCastleProvider" - } - }, - { - "name": "org.bouncycastle.jcajce.provider.keystore.BC$Mappings", - "methods": [ - { - "name": "", - "parameterTypes": [] - } - ], - "condition": { - "typeReachable": "org.bouncycastle.jce.provider.BouncyCastleProvider" - } - }, - { - "name": "org.bouncycastle.jcajce.provider.keystore.BCFKS$Mappings", - "methods": [ - { - "name": "", - "parameterTypes": [] - } - ], - "condition": { - "typeReachable": "org.bouncycastle.jce.provider.BouncyCastleProvider" - } - }, - { - "name": "org.bouncycastle.jcajce.provider.keystore.PKCS12$Mappings", - "methods": [ - { - "name": "", - "parameterTypes": [] - } - ], - "condition": { - "typeReachable": "org.bouncycastle.jce.provider.BouncyCastleProvider" - } - }, - { - "name": "org.bouncycastle.jcajce.provider.symmetric.AES$AlgParams", - "methods": [ - { - "name": "", - "parameterTypes": [] - } - ], - "condition": { - "typeReachable": "org.bouncycastle.jce.provider.BouncyCastleProvider" - } - }, - { - "name": "org.bouncycastle.jcajce.provider.symmetric.AES$ECB", - "methods": [ - { - "name": "", - "parameterTypes": [] - } - ], - "condition": { - "typeReachable": "org.bouncycastle.jce.provider.BouncyCastleProvider" - } - }, - { - "name": "org.bouncycastle.jcajce.provider.symmetric.AES$Mappings", - "methods": [ - { - "name": "", - "parameterTypes": [] - } - ], - "condition": { - "typeReachable": "org.bouncycastle.jce.provider.BouncyCastleProvider" - } - }, - { - "name": "org.bouncycastle.jcajce.provider.symmetric.ARC4$Mappings", - "methods": [ - { - "name": "", - "parameterTypes": [] - } - ], - "condition": { - "typeReachable": "org.bouncycastle.jce.provider.BouncyCastleProvider" - } - }, - { - "name": "org.bouncycastle.jcajce.provider.symmetric.ARIA$Mappings", - "methods": [ - { - "name": "", - "parameterTypes": [] - } - ], - "condition": { - "typeReachable": "org.bouncycastle.jce.provider.BouncyCastleProvider" - } - }, - { - "name": "org.bouncycastle.jcajce.provider.symmetric.Blowfish$Mappings", - "methods": [ - { - "name": "", - "parameterTypes": [] - } - ], - "condition": { - "typeReachable": "org.bouncycastle.jce.provider.BouncyCastleProvider" - } - }, - { - "name": "org.bouncycastle.jcajce.provider.symmetric.CAST5$Mappings", - "methods": [ - { - "name": "", - "parameterTypes": [] - } - ], - "condition": { - "typeReachable": "org.bouncycastle.jce.provider.BouncyCastleProvider" - } - }, - { - "name": "org.bouncycastle.jcajce.provider.symmetric.CAST6$Mappings", - "methods": [ - { - "name": "", - "parameterTypes": [] - } - ], - "condition": { - "typeReachable": "org.bouncycastle.jce.provider.BouncyCastleProvider" - } - }, - { - "name": "org.bouncycastle.jcajce.provider.symmetric.Camellia$Mappings", - "methods": [ - { - "name": "", - "parameterTypes": [] - } - ], - "condition": { - "typeReachable": "org.bouncycastle.jce.provider.BouncyCastleProvider" - } - }, - { - "name": "org.bouncycastle.jcajce.provider.symmetric.ChaCha$Mappings", - "methods": [ - { - "name": "", - "parameterTypes": [] - } - ], - "condition": { - "typeReachable": "org.bouncycastle.jce.provider.BouncyCastleProvider" - } - }, - { - "name": "org.bouncycastle.jcajce.provider.symmetric.DES$Mappings", - "methods": [ - { - "name": "", - "parameterTypes": [] - } - ], - "condition": { - "typeReachable": "org.bouncycastle.jce.provider.BouncyCastleProvider" - } - }, - { - "name": "org.bouncycastle.jcajce.provider.symmetric.DESede$Mappings", - "methods": [ - { - "name": "", - "parameterTypes": [] - } - ], - "condition": { - "typeReachable": "org.bouncycastle.jce.provider.BouncyCastleProvider" - } - }, - { - "name": "org.bouncycastle.jcajce.provider.symmetric.DSTU7624$Mappings", - "methods": [ - { - "name": "", - "parameterTypes": [] - } - ], - "condition": { - "typeReachable": "org.bouncycastle.jce.provider.BouncyCastleProvider" - } - }, - { - "name": "org.bouncycastle.jcajce.provider.symmetric.GOST28147$Mappings", - "methods": [ - { - "name": "", - "parameterTypes": [] - } - ], - "condition": { - "typeReachable": "org.bouncycastle.jce.provider.BouncyCastleProvider" - } - }, - { - "name": "org.bouncycastle.jcajce.provider.symmetric.GOST3412_2015$Mappings", - "methods": [ - { - "name": "", - "parameterTypes": [] - } - ], - "condition": { - "typeReachable": "org.bouncycastle.jce.provider.BouncyCastleProvider" - } - }, - { - "name": "org.bouncycastle.jcajce.provider.symmetric.Grain128$Mappings", - "methods": [ - { - "name": "", - "parameterTypes": [] - } - ], - "condition": { - "typeReachable": "org.bouncycastle.jce.provider.BouncyCastleProvider" - } - }, - { - "name": "org.bouncycastle.jcajce.provider.symmetric.Grainv1$Mappings", - "methods": [ - { - "name": "", - "parameterTypes": [] - } - ], - "condition": { - "typeReachable": "org.bouncycastle.jce.provider.BouncyCastleProvider" - } - }, - { - "name": "org.bouncycastle.jcajce.provider.symmetric.HC128$Mappings", - "methods": [ - { - "name": "", - "parameterTypes": [] - } - ], - "condition": { - "typeReachable": "org.bouncycastle.jce.provider.BouncyCastleProvider" - } - }, - { - "name": "org.bouncycastle.jcajce.provider.symmetric.HC256$Mappings", - "methods": [ - { - "name": "", - "parameterTypes": [] - } - ], - "condition": { - "typeReachable": "org.bouncycastle.jce.provider.BouncyCastleProvider" - } - }, - { - "name": "org.bouncycastle.jcajce.provider.symmetric.IDEA$Mappings", - "methods": [ - { - "name": "", - "parameterTypes": [] - } - ], - "condition": { - "typeReachable": "org.bouncycastle.jce.provider.BouncyCastleProvider" - } - }, - { - "name": "org.bouncycastle.jcajce.provider.symmetric.Noekeon$Mappings", - "methods": [ - { - "name": "", - "parameterTypes": [] - } - ], - "condition": { - "typeReachable": "org.bouncycastle.jce.provider.BouncyCastleProvider" - } - }, - { - "name": "org.bouncycastle.jcajce.provider.symmetric.OpenSSLPBKDF$Mappings", - "methods": [ - { - "name": "", - "parameterTypes": [] - } - ], - "condition": { - "typeReachable": "org.bouncycastle.jce.provider.BouncyCastleProvider" - } - }, - { - "name": "org.bouncycastle.jcajce.provider.symmetric.PBEPBKDF1$Mappings", - "methods": [ - { - "name": "", - "parameterTypes": [] - } - ], - "condition": { - "typeReachable": "org.bouncycastle.jce.provider.BouncyCastleProvider" - } - }, - { - "name": "org.bouncycastle.jcajce.provider.symmetric.PBEPBKDF2$Mappings", - "methods": [ - { - "name": "", - "parameterTypes": [] - } - ], - "condition": { - "typeReachable": "org.bouncycastle.jce.provider.BouncyCastleProvider" - } - }, - { - "name": "org.bouncycastle.jcajce.provider.symmetric.PBEPBKDF2$PBKDF2withSHA256", - "methods": [ - { - "name": "", - "parameterTypes": [] - } - ], - "condition": { - "typeReachable": "org.bouncycastle.jce.provider.BouncyCastleProvider" - } - }, - { - "name": "org.bouncycastle.jcajce.provider.symmetric.PBEPKCS12$Mappings", - "methods": [ - { - "name": "", - "parameterTypes": [] - } - ], - "condition": { - "typeReachable": "org.bouncycastle.jce.provider.BouncyCastleProvider" - } - }, - { - "name": "org.bouncycastle.jcajce.provider.symmetric.Poly1305$Mappings", - "methods": [ - { - "name": "", - "parameterTypes": [] - } - ], - "condition": { - "typeReachable": "org.bouncycastle.jce.provider.BouncyCastleProvider" - } - }, - { - "name": "org.bouncycastle.jcajce.provider.symmetric.RC2$Mappings", - "methods": [ - { - "name": "", - "parameterTypes": [] - } - ], - "condition": { - "typeReachable": "org.bouncycastle.jce.provider.BouncyCastleProvider" - } - }, - { - "name": "org.bouncycastle.jcajce.provider.symmetric.RC5$Mappings", - "methods": [ - { - "name": "", - "parameterTypes": [] - } - ], - "condition": { - "typeReachable": "org.bouncycastle.jce.provider.BouncyCastleProvider" - } - }, - { - "name": "org.bouncycastle.jcajce.provider.symmetric.RC6$Mappings", - "methods": [ - { - "name": "", - "parameterTypes": [] - } - ], - "condition": { - "typeReachable": "org.bouncycastle.jce.provider.BouncyCastleProvider" - } - }, - { - "name": "org.bouncycastle.jcajce.provider.symmetric.Rijndael$Mappings", - "methods": [ - { - "name": "", - "parameterTypes": [] - } - ], - "condition": { - "typeReachable": "org.bouncycastle.jce.provider.BouncyCastleProvider" - } - }, - { - "name": "org.bouncycastle.jcajce.provider.symmetric.SCRYPT$Mappings", - "methods": [ - { - "name": "", - "parameterTypes": [] - } - ], - "condition": { - "typeReachable": "org.bouncycastle.jce.provider.BouncyCastleProvider" - } - }, - { - "name": "org.bouncycastle.jcajce.provider.symmetric.SEED$Mappings", - "methods": [ - { - "name": "", - "parameterTypes": [] - } - ], - "condition": { - "typeReachable": "org.bouncycastle.jce.provider.BouncyCastleProvider" - } - }, - { - "name": "org.bouncycastle.jcajce.provider.symmetric.SM4$Mappings", - "methods": [ - { - "name": "", - "parameterTypes": [] - } - ], - "condition": { - "typeReachable": "org.bouncycastle.jce.provider.BouncyCastleProvider" - } - }, - { - "name": "org.bouncycastle.jcajce.provider.symmetric.Salsa20$Mappings", - "methods": [ - { - "name": "", - "parameterTypes": [] - } - ], - "condition": { - "typeReachable": "org.bouncycastle.jce.provider.BouncyCastleProvider" - } - }, - { - "name": "org.bouncycastle.jcajce.provider.symmetric.Serpent$Mappings", - "methods": [ - { - "name": "", - "parameterTypes": [] - } - ], - "condition": { - "typeReachable": "org.bouncycastle.jce.provider.BouncyCastleProvider" - } - }, - { - "name": "org.bouncycastle.jcajce.provider.symmetric.Shacal2$Mappings", - "methods": [ - { - "name": "", - "parameterTypes": [] - } - ], - "condition": { - "typeReachable": "org.bouncycastle.jce.provider.BouncyCastleProvider" - } - }, - { - "name": "org.bouncycastle.jcajce.provider.symmetric.SipHash$Mappings", - "methods": [ - { - "name": "", - "parameterTypes": [] - } - ], - "condition": { - "typeReachable": "org.bouncycastle.jce.provider.BouncyCastleProvider" - } - }, - { - "name": "org.bouncycastle.jcajce.provider.symmetric.SipHash128$Mappings", - "methods": [ - { - "name": "", - "parameterTypes": [] - } - ], - "condition": { - "typeReachable": "org.bouncycastle.jce.provider.BouncyCastleProvider" - } - }, - { - "name": "org.bouncycastle.jcajce.provider.symmetric.Skipjack$Mappings", - "methods": [ - { - "name": "", - "parameterTypes": [] - } - ], - "condition": { - "typeReachable": "org.bouncycastle.jce.provider.BouncyCastleProvider" - } - }, - { - "name": "org.bouncycastle.jcajce.provider.symmetric.TEA$Mappings", - "methods": [ - { - "name": "", - "parameterTypes": [] - } - ], - "condition": { - "typeReachable": "org.bouncycastle.jce.provider.BouncyCastleProvider" - } - }, - { - "name": "org.bouncycastle.jcajce.provider.symmetric.TLSKDF$Mappings", - "methods": [ - { - "name": "", - "parameterTypes": [] - } - ], - "condition": { - "typeReachable": "org.bouncycastle.jce.provider.BouncyCastleProvider" - } - }, - { - "name": "org.bouncycastle.jcajce.provider.symmetric.Threefish$Mappings", - "methods": [ - { - "name": "", - "parameterTypes": [] - } - ], - "condition": { - "typeReachable": "org.bouncycastle.jce.provider.BouncyCastleProvider" - } - }, - { - "name": "org.bouncycastle.jcajce.provider.symmetric.Twofish$Mappings", - "methods": [ - { - "name": "", - "parameterTypes": [] - } - ], - "condition": { - "typeReachable": "org.bouncycastle.jce.provider.BouncyCastleProvider" - } - }, - { - "name": "org.bouncycastle.jcajce.provider.symmetric.VMPC$Mappings", - "methods": [ - { - "name": "", - "parameterTypes": [] - } - ], - "condition": { - "typeReachable": "org.bouncycastle.jce.provider.BouncyCastleProvider" - } + ] }, { - "name": "org.bouncycastle.jcajce.provider.symmetric.VMPCKSA3$Mappings", + "name": "com.sun.crypto.provider.AESKeyGenerator", "methods": [ { "name": "", "parameterTypes": [] } - ], - "condition": { - "typeReachable": "org.bouncycastle.jce.provider.BouncyCastleProvider" - } + ] }, { - "name": "org.bouncycastle.jcajce.provider.symmetric.XSalsa20$Mappings", + "name": "com.sun.crypto.provider.ARCFOURCipher", "methods": [ { "name": "", "parameterTypes": [] } - ], - "condition": { - "typeReachable": "org.bouncycastle.jce.provider.BouncyCastleProvider" - } + ] }, { - "name": "org.bouncycastle.jcajce.provider.symmetric.XTEA$Mappings", + "name": "com.sun.crypto.provider.ChaCha20Cipher$ChaCha20Poly1305", "methods": [ { "name": "", "parameterTypes": [] } - ], - "condition": { - "typeReachable": "org.bouncycastle.jce.provider.BouncyCastleProvider" - } + ] }, { - "name": "org.bouncycastle.jcajce.provider.symmetric.Zuc$Mappings", + "name": "com.sun.crypto.provider.DESCipher", "methods": [ { "name": "", "parameterTypes": [] } - ], - "condition": { - "typeReachable": "org.bouncycastle.jce.provider.BouncyCastleProvider" - } + ] }, { - "name": "org.bouncycastle.pqc.jcajce.provider.BIKE$Mappings", + "name": "com.sun.crypto.provider.DESedeCipher", "methods": [ { "name": "", "parameterTypes": [] } - ], - "condition": { - "typeReachable": "org.bouncycastle.jce.provider.BouncyCastleProvider" - } + ] }, { - "name": "org.bouncycastle.pqc.jcajce.provider.CMCE$Mappings", + "name": "com.sun.crypto.provider.DHParameters", "methods": [ { "name": "", "parameterTypes": [] } - ], - "condition": { - "typeReachable": "org.bouncycastle.jce.provider.BouncyCastleProvider" - } + ] }, { - "name": "org.bouncycastle.pqc.jcajce.provider.Dilithium$Mappings", + "name": "com.sun.crypto.provider.GaloisCounterMode$AESGCM", "methods": [ { "name": "", "parameterTypes": [] } - ], - "condition": { - "typeReachable": "org.bouncycastle.jce.provider.BouncyCastleProvider" - } + ] }, { - "name": "org.bouncycastle.pqc.jcajce.provider.Falcon$Mappings", + "name": "com.sun.crypto.provider.HmacCore$HmacSHA384", "methods": [ { "name": "", "parameterTypes": [] } - ], - "condition": { - "typeReachable": "org.bouncycastle.jce.provider.BouncyCastleProvider" - } + ] }, { - "name": "org.bouncycastle.pqc.jcajce.provider.Frodo$Mappings", + "name": "com.sun.crypto.provider.TlsKeyMaterialGenerator", "methods": [ { "name": "", "parameterTypes": [] } - ], - "condition": { - "typeReachable": "org.bouncycastle.jce.provider.BouncyCastleProvider" - } + ] }, { - "name": "org.bouncycastle.pqc.jcajce.provider.HQC$Mappings", + "name": "com.sun.crypto.provider.TlsMasterSecretGenerator", "methods": [ { "name": "", "parameterTypes": [] } - ], - "condition": { - "typeReachable": "org.bouncycastle.jce.provider.BouncyCastleProvider" - } + ] }, { - "name": "org.bouncycastle.pqc.jcajce.provider.Kyber$Mappings", + "name": "com.sun.crypto.provider.TlsPrfGenerator$V12", "methods": [ { "name": "", "parameterTypes": [] } - ], - "condition": { - "typeReachable": "org.bouncycastle.jce.provider.BouncyCastleProvider" - } + ] }, { - "name": "org.bouncycastle.pqc.jcajce.provider.LMS$Mappings", - "methods": [ - { - "name": "", - "parameterTypes": [] - } - ], - "condition": { - "typeReachable": "org.bouncycastle.jce.provider.BouncyCastleProvider" - } + "name": "java.security.KeyStoreSpi" }, { - "name": "org.bouncycastle.pqc.jcajce.provider.NH$Mappings", - "methods": [ - { - "name": "", - "parameterTypes": [] - } - ], - "condition": { - "typeReachable": "org.bouncycastle.jce.provider.BouncyCastleProvider" - } + "name": "java.security.cert.PKIXRevocationChecker" }, { - "name": "org.bouncycastle.pqc.jcajce.provider.NTRU$Mappings", - "methods": [ - { - "name": "", - "parameterTypes": [] - } - ], - "condition": { - "typeReachable": "org.bouncycastle.jce.provider.BouncyCastleProvider" - } + "name": "java.security.interfaces.DSAPrivateKey" }, { - "name": "org.bouncycastle.pqc.jcajce.provider.NTRUPrime$Mappings", - "methods": [ - { - "name": "", - "parameterTypes": [] - } - ], - "condition": { - "typeReachable": "org.bouncycastle.jce.provider.BouncyCastleProvider" - } + "name": "java.security.interfaces.DSAPublicKey" }, { - "name": "org.bouncycastle.pqc.jcajce.provider.Picnic$Mappings", - "methods": [ - { - "name": "", - "parameterTypes": [] - } - ], - "condition": { - "typeReachable": "org.bouncycastle.jce.provider.BouncyCastleProvider" - } + "name": "java.security.interfaces.ECPrivateKey" }, { - "name": "org.bouncycastle.pqc.jcajce.provider.Rainbow$Mappings", - "methods": [ - { - "name": "", - "parameterTypes": [] - } - ], - "condition": { - "typeReachable": "org.bouncycastle.jce.provider.BouncyCastleProvider" - } + "name": "java.security.interfaces.ECPublicKey" }, { - "name": "org.bouncycastle.pqc.jcajce.provider.SABER$Mappings", - "methods": [ - { - "name": "", - "parameterTypes": [] - } - ], - "condition": { - "typeReachable": "org.bouncycastle.jce.provider.BouncyCastleProvider" - } + "name": "java.security.interfaces.RSAPrivateKey" }, { - "name": "org.bouncycastle.pqc.jcajce.provider.SPHINCS$Mappings", - "methods": [ - { - "name": "", - "parameterTypes": [] - } - ], - "condition": { - "typeReachable": "org.bouncycastle.jce.provider.BouncyCastleProvider" - } + "name": "java.security.interfaces.RSAPublicKey" }, { - "name": "org.bouncycastle.pqc.jcajce.provider.SPHINCSPlus$Mappings", - "methods": [ - { - "name": "", - "parameterTypes": [] - } - ], - "condition": { - "typeReachable": "org.bouncycastle.jce.provider.BouncyCastleProvider" - } + "name": "java.security.spec.DSAParameterSpec" }, { - "name": "org.bouncycastle.pqc.jcajce.provider.XMSS$Mappings", - "methods": [ - { - "name": "", - "parameterTypes": [] - } - ], - "condition": { - "typeReachable": "org.bouncycastle.jce.provider.BouncyCastleProvider" - } + "name": "javax.crypto.spec.GCMParameterSpec" }, { "name": "sun.security.pkcs12.PKCS12KeyStore", @@ -2277,10 +219,7 @@ "name": "", "parameterTypes": [] } - ], - "condition": { - "typeReachable": "org.bouncycastle.jce.provider.BouncyCastleProvider" - } + ] }, { "name": "sun.security.pkcs12.PKCS12KeyStore$DualFormatPKCS12", @@ -2289,10 +228,7 @@ "name": "", "parameterTypes": [] } - ], - "condition": { - "typeReachable": "org.bouncycastle.jce.provider.BouncyCastleProvider" - } + ] }, { "name": "sun.security.provider.DSA$SHA1withDSA", @@ -2301,10 +237,7 @@ "name": "", "parameterTypes": [] } - ], - "condition": { - "typeReachable": "org.bouncycastle.jce.provider.BouncyCastleProvider" - } + ] }, { "name": "sun.security.provider.DSA$SHA224withDSA", @@ -2313,10 +246,7 @@ "name": "", "parameterTypes": [] } - ], - "condition": { - "typeReachable": "org.bouncycastle.jce.provider.BouncyCastleProvider" - } + ] }, { "name": "sun.security.provider.DSA$SHA256withDSA", @@ -2325,10 +255,7 @@ "name": "", "parameterTypes": [] } - ], - "condition": { - "typeReachable": "org.bouncycastle.jce.provider.BouncyCastleProvider" - } + ] }, { "name": "sun.security.provider.DSAKeyFactory", @@ -2337,10 +264,7 @@ "name": "", "parameterTypes": [] } - ], - "condition": { - "typeReachable": "org.bouncycastle.jce.provider.BouncyCastleProvider" - } + ] }, { "name": "sun.security.provider.DSAParameters", @@ -2349,10 +273,7 @@ "name": "", "parameterTypes": [] } - ], - "condition": { - "typeReachable": "org.bouncycastle.jce.provider.BouncyCastleProvider" - } + ] }, { "name": "sun.security.provider.JavaKeyStore$DualFormatJKS", @@ -2361,10 +282,7 @@ "name": "", "parameterTypes": [] } - ], - "condition": { - "typeReachable": "org.bouncycastle.jce.provider.BouncyCastleProvider" - } + ] }, { "name": "sun.security.provider.JavaKeyStore$JKS", @@ -2373,10 +291,7 @@ "name": "", "parameterTypes": [] } - ], - "condition": { - "typeReachable": "org.bouncycastle.jce.provider.BouncyCastleProvider" - } + ] }, { "name": "sun.security.provider.MD2", @@ -2385,10 +300,7 @@ "name": "", "parameterTypes": [] } - ], - "condition": { - "typeReachable": "org.bouncycastle.jce.provider.BouncyCastleProvider" - } + ] }, { "name": "sun.security.provider.MD5", @@ -2397,10 +309,7 @@ "name": "", "parameterTypes": [] } - ], - "condition": { - "typeReachable": "org.bouncycastle.jce.provider.BouncyCastleProvider" - } + ] }, { "name": "sun.security.provider.NativePRNG", @@ -2411,10 +320,7 @@ "java.security.SecureRandomParameters" ] } - ], - "condition": { - "typeReachable": "org.bouncycastle.jce.provider.BouncyCastleProvider" - } + ] }, { "name": "sun.security.provider.NativePRNG$NonBlocking", @@ -2425,10 +331,7 @@ "java.security.SecureRandomParameters" ] } - ], - "condition": { - "typeReachable": "org.bouncycastle.jce.provider.BouncyCastleProvider" - } + ] }, { "name": "sun.security.provider.SHA", @@ -2437,10 +340,7 @@ "name": "", "parameterTypes": [] } - ], - "condition": { - "typeReachable": "org.bouncycastle.jce.provider.BouncyCastleProvider" - } + ] }, { "name": "sun.security.provider.SHA2$SHA224", @@ -2449,10 +349,7 @@ "name": "", "parameterTypes": [] } - ], - "condition": { - "typeReachable": "org.bouncycastle.jce.provider.BouncyCastleProvider" - } + ] }, { "name": "sun.security.provider.SHA2$SHA256", @@ -2461,10 +358,7 @@ "name": "", "parameterTypes": [] } - ], - "condition": { - "typeReachable": "org.bouncycastle.jce.provider.BouncyCastleProvider" - } + ] }, { "name": "sun.security.provider.SHA3$SHA224", @@ -2473,10 +367,7 @@ "name": "", "parameterTypes": [] } - ], - "condition": { - "typeReachable": "org.bouncycastle.jce.provider.BouncyCastleProvider" - } + ] }, { "name": "sun.security.provider.SHA3$SHA256", @@ -2485,10 +376,7 @@ "name": "", "parameterTypes": [] } - ], - "condition": { - "typeReachable": "org.bouncycastle.jce.provider.BouncyCastleProvider" - } + ] }, { "name": "sun.security.provider.SHA3$SHA384", @@ -2497,10 +385,7 @@ "name": "", "parameterTypes": [] } - ], - "condition": { - "typeReachable": "org.bouncycastle.jce.provider.BouncyCastleProvider" - } + ] }, { "name": "sun.security.provider.SHA3$SHA512", @@ -2509,10 +394,7 @@ "name": "", "parameterTypes": [] } - ], - "condition": { - "typeReachable": "org.bouncycastle.jce.provider.BouncyCastleProvider" - } + ] }, { "name": "sun.security.provider.SHA5$SHA384", @@ -2521,10 +403,7 @@ "name": "", "parameterTypes": [] } - ], - "condition": { - "typeReachable": "org.bouncycastle.jce.provider.BouncyCastleProvider" - } + ] }, { "name": "sun.security.provider.SHA5$SHA512", @@ -2533,10 +412,7 @@ "name": "", "parameterTypes": [] } - ], - "condition": { - "typeReachable": "org.bouncycastle.jce.provider.BouncyCastleProvider" - } + ] }, { "name": "sun.security.provider.SHA5$SHA512_224", @@ -2545,10 +421,7 @@ "name": "", "parameterTypes": [] } - ], - "condition": { - "typeReachable": "org.bouncycastle.jce.provider.BouncyCastleProvider" - } + ] }, { "name": "sun.security.provider.SHA5$SHA512_256", @@ -2557,10 +430,7 @@ "name": "", "parameterTypes": [] } - ], - "condition": { - "typeReachable": "org.bouncycastle.jce.provider.BouncyCastleProvider" - } + ] }, { "name": "sun.security.provider.X509Factory", @@ -2569,10 +439,7 @@ "name": "", "parameterTypes": [] } - ], - "condition": { - "typeReachable": "org.bouncycastle.jce.provider.BouncyCastleProvider" - } + ] }, { "name": "sun.security.provider.certpath.CollectionCertStore", @@ -2583,10 +450,7 @@ "java.security.cert.CertStoreParameters" ] } - ], - "condition": { - "typeReachable": "org.bouncycastle.jce.provider.BouncyCastleProvider" - } + ] }, { "name": "sun.security.provider.certpath.PKIXCertPathValidator", @@ -2595,10 +459,7 @@ "name": "", "parameterTypes": [] } - ], - "condition": { - "typeReachable": "org.bouncycastle.jce.provider.BouncyCastleProvider" - } + ] }, { "name": "sun.security.provider.certpath.SunCertPathBuilder", @@ -2607,10 +468,7 @@ "name": "", "parameterTypes": [] } - ], - "condition": { - "typeReachable": "org.bouncycastle.jce.provider.BouncyCastleProvider" - } + ] }, { "name": "sun.security.rsa.PSSParameters", @@ -2619,10 +477,7 @@ "name": "", "parameterTypes": [] } - ], - "condition": { - "typeReachable": "org.bouncycastle.jce.provider.BouncyCastleProvider" - } + ] }, { "name": "sun.security.rsa.RSAKeyFactory$Legacy", @@ -2631,10 +486,7 @@ "name": "", "parameterTypes": [] } - ], - "condition": { - "typeReachable": "org.bouncycastle.jce.provider.BouncyCastleProvider" - } + ] }, { "name": "sun.security.rsa.RSAPSSSignature", @@ -2643,10 +495,7 @@ "name": "", "parameterTypes": [] } - ], - "condition": { - "typeReachable": "org.bouncycastle.jce.provider.BouncyCastleProvider" - } + ] }, { "name": "sun.security.rsa.RSASignature$MD5withRSA", @@ -2655,10 +504,7 @@ "name": "", "parameterTypes": [] } - ], - "condition": { - "typeReachable": "org.bouncycastle.jce.provider.BouncyCastleProvider" - } + ] }, { "name": "sun.security.rsa.RSASignature$SHA224withRSA", @@ -2667,10 +513,7 @@ "name": "", "parameterTypes": [] } - ], - "condition": { - "typeReachable": "org.bouncycastle.jce.provider.BouncyCastleProvider" - } + ] }, { "name": "sun.security.rsa.RSASignature$SHA256withRSA", @@ -2679,10 +522,7 @@ "name": "", "parameterTypes": [] } - ], - "condition": { - "typeReachable": "org.bouncycastle.jce.provider.BouncyCastleProvider" - } + ] }, { "name": "sun.security.ssl.KeyManagerFactoryImpl$SunX509", @@ -2691,10 +531,7 @@ "name": "", "parameterTypes": [] } - ], - "condition": { - "typeReachable": "org.bouncycastle.jce.provider.BouncyCastleProvider" - } + ] }, { "name": "sun.security.ssl.SSLContextImpl$TLSContext", @@ -2703,10 +540,7 @@ "name": "", "parameterTypes": [] } - ], - "condition": { - "typeReachable": "org.bouncycastle.jce.provider.BouncyCastleProvider" - } + ] }, { "name": "sun.security.ssl.TrustManagerFactoryImpl$PKIXFactory", @@ -2715,10 +549,7 @@ "name": "", "parameterTypes": [] } - ], - "condition": { - "typeReachable": "org.bouncycastle.jce.provider.BouncyCastleProvider" - } + ] }, { "name": "sun.security.x509.AuthorityInfoAccessExtension", @@ -2730,10 +561,7 @@ "java.lang.Object" ] } - ], - "condition": { - "typeReachable": "org.bouncycastle.jce.provider.BouncyCastleProvider" - } + ] }, { "name": "sun.security.x509.AuthorityKeyIdentifierExtension", @@ -2745,10 +573,7 @@ "java.lang.Object" ] } - ], - "condition": { - "typeReachable": "org.bouncycastle.jce.provider.BouncyCastleProvider" - } + ] }, { "name": "sun.security.x509.BasicConstraintsExtension", @@ -2760,10 +585,7 @@ "java.lang.Object" ] } - ], - "condition": { - "typeReachable": "org.bouncycastle.jce.provider.BouncyCastleProvider" - } + ] }, { "name": "sun.security.x509.CRLDistributionPointsExtension", @@ -2780,10 +602,7 @@ "java.lang.Object" ] } - ], - "condition": { - "typeReachable": "org.bouncycastle.jce.provider.BouncyCastleProvider" - } + ] }, { "name": "sun.security.x509.CRLNumberExtension", @@ -2795,10 +614,7 @@ "java.lang.Object" ] } - ], - "condition": { - "typeReachable": "org.bouncycastle.jce.provider.BouncyCastleProvider" - } + ] }, { "name": "sun.security.x509.CertificatePoliciesExtension", @@ -2810,10 +626,7 @@ "java.lang.Object" ] } - ], - "condition": { - "typeReachable": "org.bouncycastle.jce.provider.BouncyCastleProvider" - } + ] }, { "name": "sun.security.x509.ExtendedKeyUsageExtension", @@ -2825,10 +638,7 @@ "java.lang.Object" ] } - ], - "condition": { - "typeReachable": "org.bouncycastle.jce.provider.BouncyCastleProvider" - } + ] }, { "name": "sun.security.x509.IssuerAlternativeNameExtension", @@ -2845,10 +655,7 @@ "java.lang.Object" ] } - ], - "condition": { - "typeReachable": "org.bouncycastle.jce.provider.BouncyCastleProvider" - } + ] }, { "name": "sun.security.x509.KeyUsageExtension", @@ -2860,10 +667,7 @@ "java.lang.Object" ] } - ], - "condition": { - "typeReachable": "org.bouncycastle.jce.provider.BouncyCastleProvider" - } + ] }, { "name": "sun.security.x509.NetscapeCertTypeExtension", @@ -2875,10 +679,7 @@ "java.lang.Object" ] } - ], - "condition": { - "typeReachable": "org.bouncycastle.jce.provider.BouncyCastleProvider" - } + ] }, { "name": "sun.security.x509.PrivateKeyUsageExtension", @@ -2890,10 +691,7 @@ "java.lang.Object" ] } - ], - "condition": { - "typeReachable": "org.bouncycastle.jce.provider.BouncyCastleProvider" - } + ] }, { "name": "sun.security.x509.SubjectAlternativeNameExtension", @@ -2905,10 +703,7 @@ "java.lang.Object" ] } - ], - "condition": { - "typeReachable": "org.bouncycastle.jce.provider.BouncyCastleProvider" - } + ] }, { "name": "sun.security.x509.SubjectKeyIdentifierExtension", @@ -2920,9 +715,6 @@ "java.lang.Object" ] } - ], - "condition": { - "typeReachable": "org.bouncycastle.jce.provider.BouncyCastleProvider" - } + ] } ] diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/BouncyCastleFeature.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/BouncyCastleFeature.java deleted file mode 100644 index a076b1625d..0000000000 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/BouncyCastleFeature.java +++ /dev/null @@ -1,108 +0,0 @@ -/* - * Copyright (c) 2022, 2025, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * The Universal Permissive License (UPL), Version 1.0 - * - * Subject to the condition set forth below, permission is hereby granted to any - * person obtaining a copy of this software, associated documentation and/or - * data (collectively the "Software"), free of charge and under any and all - * copyright rights in the Software, and any and all patent rights owned or - * freely licensable by each licensor hereunder covering either (i) the - * unmodified Software as contributed to or provided by such licensor, or (ii) - * the Larger Works (as defined below), to deal in both - * - * (a) the Software, and - * - * (b) any piece of software and/or hardware listed in the lrgrwrks.txt file if - * one is included with the Software each a "Larger Work" to which the Software - * is contributed by such licensors), - * - * without restriction, including without limitation the rights to copy, create - * derivative works of, display, perform, and distribute the Software and make, - * use, sell, offer for sale, import, export, have made, and have sold the - * Software and the Larger Work(s), and to sublicense the foregoing rights on - * either these or other terms. - * - * This license is subject to the following condition: - * - * The above copyright notice and either this complete permission notice or at a - * minimum a reference to the UPL must be included in all copies or substantial - * portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ -package com.oracle.graal.python; - -import java.security.Security; - -import org.bouncycastle.jce.provider.BouncyCastleProvider; -import org.graalvm.nativeimage.ImageSingletons; -import org.graalvm.nativeimage.hosted.Feature; -import org.graalvm.nativeimage.hosted.RuntimeReflection; -import org.graalvm.nativeimage.impl.RuntimeClassInitializationSupport; - -import com.oracle.graal.python.builtins.objects.ssl.LazyBouncyCastleProvider; -import com.oracle.graal.python.runtime.PythonImageBuildOptions; - -public class BouncyCastleFeature implements Feature { - - /* - * Will soon be default in native image. We'll still need the old way to support older - * native-image in JDK 21. I guess then it would be something like: - * - * INITIALIZE_AT_RUNTIME = Runtime.version().feature() >= 26; - */ - private static final boolean INITIALIZE_AT_RUNTIME = false; - - @Override - public void afterRegistration(AfterRegistrationAccess access) { - if (!PythonImageBuildOptions.WITHOUT_SSL) { - RuntimeClassInitializationSupport support = ImageSingletons.lookup(RuntimeClassInitializationSupport.class); - - if (INITIALIZE_AT_RUNTIME) { - // Verify at build time, but reinitialize at runtime - support.initializeAtRunTime("org.bouncycastle", "security provider"); - Security.addProvider(new BouncyCastleProvider()); - } else { - support.initializeAtBuildTime("org.bouncycastle", "security provider"); - support.initializeAtRunTime("org.bouncycastle.jcajce.provider.drbg.DRBG$Default", "RNG"); - support.initializeAtRunTime("org.bouncycastle.jcajce.provider.drbg.DRBG$NonceAndIV", "RNG"); - LazyBouncyCastleProvider.initProvider(); - } - - // SSLBasicKeyDerivation looks up the classes below reflectively since jdk-25+23 - // See https://github.com/openjdk/jdk/pull/24393 - String[] reflectiveClasses = new String[]{ - "com.sun.crypto.provider.HKDFKeyDerivation$HKDFSHA256", - "com.sun.crypto.provider.HKDFKeyDerivation$HKDFSHA384", - "com.sun.crypto.provider.HKDFKeyDerivation$HKDFSHA512", - "sun.security.pkcs11.P11HKDF", - }; - for (String name : reflectiveClasses) { - try { - Class.forName(name); - } catch (SecurityException | ClassNotFoundException e) { - return; - } - } - // For backwards compatibility with older JDKs, we only do this if we found - // all those classes - Security.addProvider(Security.getProvider("SunJCE")); - for (String name : reflectiveClasses) { - try { - RuntimeReflection.register(Class.forName(name)); - RuntimeReflection.register(Class.forName(name).getConstructors()); - } catch (SecurityException | ClassNotFoundException e) { - throw new RuntimeException("Could not register " + name + " for reflective access!", e); - } - } - } - } -} diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/ImpModuleBuiltins.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/ImpModuleBuiltins.java index 448b0f3051..c1c044aee6 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/ImpModuleBuiltins.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/ImpModuleBuiltins.java @@ -54,7 +54,7 @@ import static com.oracle.graal.python.nodes.StringLiterals.T_EXT_SO; import static com.oracle.graal.python.nodes.StringLiterals.T_NAME; import static com.oracle.graal.python.runtime.exception.PythonErrorType.NotImplementedError; -import static com.oracle.graal.python.util.PythonUtils.ARRAY_ACCESSOR; +import static com.oracle.graal.python.util.PythonUtils.ARRAY_ACCESSOR_LE; import static com.oracle.graal.python.util.PythonUtils.TS_ENCODING; import static com.oracle.graal.python.util.PythonUtils.internString; import static com.oracle.graal.python.util.PythonUtils.toTruffleStringUncached; @@ -64,9 +64,6 @@ import java.util.List; import java.util.concurrent.locks.ReentrantLock; -import org.bouncycastle.crypto.macs.SipHash; -import org.bouncycastle.crypto.params.KeyParameter; - import com.oracle.graal.python.PythonLanguage; import com.oracle.graal.python.annotations.ArgumentClinic; import com.oracle.graal.python.annotations.ArgumentClinic.ClinicConversion; @@ -744,16 +741,68 @@ static PBytes run(long magicNumber, Object sourceBuffer, @TruffleBoundary public static byte[] hashSource(long magicNumber, byte[] bytes, int length) { - SipHash sipHash = new SipHash(1, 3); - byte[] key = new byte[16]; - ARRAY_ACCESSOR.putLong(key, 0, magicNumber); - sipHash.init(new KeyParameter(key)); - sipHash.update(bytes, 0, length); - byte[] out = new byte[sipHash.getMacSize()]; - sipHash.doFinal(out, 0); + long hash = sipHash13(magicNumber, 0, bytes, length); + byte[] out = new byte[Long.BYTES]; + ARRAY_ACCESSOR_LE.putLong(out, 0, hash); return out; } + private static long sipHash13(long k0, long k1, byte[] src, int length) { + long b = ((long) length) << 56; + long v0 = k0 ^ 0x736f6d6570736575L; + long v1 = k1 ^ 0x646f72616e646f6dL; + long v2 = k0 ^ 0x6c7967656e657261L; + long v3 = k1 ^ 0x7465646279746573L; + int offset = 0; + while (length - offset >= Long.BYTES) { + long mi = ARRAY_ACCESSOR_LE.getLong(src, offset); + offset += Long.BYTES; + v3 ^= mi; + long[] state = singleRound(v0, v1, v2, v3); + v0 = state[0]; + v1 = state[1]; + v2 = state[2]; + v3 = state[3]; + v0 ^= mi; + } + long tail = 0; + int remaining = length - offset; + for (int i = 0; i < remaining; i++) { + tail |= ((long) src[offset + i] & 0xffL) << (Byte.SIZE * i); + } + b |= tail; + v3 ^= b; + long[] state = singleRound(v0, v1, v2, v3); + v0 = state[0]; + v1 = state[1]; + v2 = state[2]; + v3 = state[3]; + v0 ^= b; + v2 ^= 0xff; + for (int i = 0; i < 3; i++) { + state = singleRound(v0, v1, v2, v3); + v0 = state[0]; + v1 = state[1]; + v2 = state[2]; + v3 = state[3]; + } + return (v0 ^ v1) ^ (v2 ^ v3); + } + + private static long[] singleRound(long v0, long v1, long v2, long v3) { + v0 += v1; + v2 += v3; + v1 = Long.rotateLeft(v1, 13) ^ v0; + v3 = Long.rotateLeft(v3, 16) ^ v2; + v0 = Long.rotateLeft(v0, 32); + v2 += v1; + v0 += v3; + v1 = Long.rotateLeft(v1, 17) ^ v2; + v3 = Long.rotateLeft(v3, 21) ^ v0; + v2 = Long.rotateLeft(v2, 32); + return new long[]{v0, v1, v2, v3}; + } + @Override protected ArgumentClinicProvider getArgumentClinic() { return ImpModuleBuiltinsClinicProviders.SourceHashNodeClinicProviderGen.INSTANCE; diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/MarshalModuleBuiltins.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/MarshalModuleBuiltins.java index df6c6d2861..d71bf7174c 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/MarshalModuleBuiltins.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/MarshalModuleBuiltins.java @@ -1677,6 +1677,7 @@ public PBytecodeDSLSerializer(PythonLanguage language) { this.language = language; } + @TruffleBoundary public void serialize(SerializerContext context, DataOutput buffer, Object object) throws IOException { /* * NB: Since the deserializer uses a fresh Marshal instance for each object (see below) diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/SSLModuleBuiltins.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/SSLModuleBuiltins.java index 3d9ec855b6..b5782d298c 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/SSLModuleBuiltins.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/SSLModuleBuiltins.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2021, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * The Universal Permissive License (UPL), Version 1.0 @@ -67,8 +67,6 @@ import javax.net.ssl.SSLContext; import javax.net.ssl.SSLEngine; -import org.bouncycastle.util.encoders.DecoderException; - import com.oracle.graal.python.PythonLanguage; import com.oracle.graal.python.annotations.ArgumentClinic; import com.oracle.graal.python.annotations.Builtin; @@ -79,7 +77,6 @@ import com.oracle.graal.python.builtins.objects.exception.OSErrorEnum; import com.oracle.graal.python.builtins.objects.module.PythonModule; import com.oracle.graal.python.builtins.objects.ssl.CertUtils; -import com.oracle.graal.python.builtins.objects.ssl.LazyBouncyCastleProvider; import com.oracle.graal.python.builtins.objects.ssl.SSLCipher; import com.oracle.graal.python.builtins.objects.ssl.SSLCipherSelector; import com.oracle.graal.python.builtins.objects.ssl.SSLErrorCode; @@ -219,7 +216,6 @@ private static boolean tryProtocolAvailability(SSLContext context, SSLProtocol p @Override public void postInitialize(Python3Core core) { super.postInitialize(core); - LazyBouncyCastleProvider.initProvider(); loadDefaults(core.getContext()); PythonModule module = core.lookupBuiltinModule(T__SSL); module.setAttribute(tsLiteral("OPENSSL_VERSION_NUMBER"), 0); @@ -443,7 +439,7 @@ private Object decode(Node inliningTarget, PConstructAndRaiseNode.Lazy construct throw constructAndRaiseNode.get(inliningTarget).raiseSSLError(null, SSL_ERR_DECODING_PEM_FILE_UNEXPECTED_S, cert.getClass().getName()); } return CertUtils.decodeCertificate(inliningTarget, constructAndRaiseNode, (X509Certificate) certs.get(0), PythonLanguage.get(null)); - } catch (IOException | DecoderException ex) { + } catch (IOException ex) { throw constructAndRaiseNode.get(inliningTarget).raiseSSLError(null, SSL_CANT_OPEN_FILE_S, ex.toString()); } catch (CertificateException | CRLException ex) { throw constructAndRaiseNode.get(inliningTarget).raiseSSLError(null, SSL_ERR_DECODING_PEM_FILE_S, ex.toString()); diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/hashlib/HashlibModuleBuiltins.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/hashlib/HashlibModuleBuiltins.java index 5817b3427f..9d52fc10f1 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/hashlib/HashlibModuleBuiltins.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/hashlib/HashlibModuleBuiltins.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2022, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * The Universal Permissive License (UPL), Version 1.0 @@ -56,6 +56,8 @@ import static com.oracle.graal.python.util.PythonUtils.toTruffleStringUncached; import static com.oracle.graal.python.util.PythonUtils.tsLiteral; +import java.nio.ByteBuffer; +import java.security.GeneralSecurityException; import java.security.InvalidKeyException; import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; @@ -67,12 +69,6 @@ import javax.crypto.Mac; import javax.crypto.spec.SecretKeySpec; -import org.bouncycastle.crypto.CipherParameters; -import org.bouncycastle.crypto.Digest; -import org.bouncycastle.crypto.generators.PKCS5S2ParametersGenerator; -import org.bouncycastle.crypto.params.KeyParameter; -import org.bouncycastle.jcajce.provider.util.DigestFactory; - import com.oracle.graal.python.PythonLanguage; import com.oracle.graal.python.annotations.ArgumentClinic; import com.oracle.graal.python.annotations.Builtin; @@ -88,7 +84,6 @@ import com.oracle.graal.python.builtins.objects.common.EconomicMapStorage; import com.oracle.graal.python.builtins.objects.common.HashingStorageNodes; import com.oracle.graal.python.builtins.objects.module.PythonModule; -import com.oracle.graal.python.builtins.objects.ssl.LazyBouncyCastleProvider; import com.oracle.graal.python.lib.PyLongAsLongNode; import com.oracle.graal.python.nodes.ErrorMessages; import com.oracle.graal.python.nodes.PGuards; @@ -104,8 +99,8 @@ import com.oracle.graal.python.nodes.util.CastToJavaStringNode; import com.oracle.graal.python.nodes.util.CastToTruffleStringNode; import com.oracle.graal.python.runtime.IndirectCallData.InteropCallData; +import com.oracle.graal.python.runtime.crypto.BouncyCastleSupportProvider; import com.oracle.graal.python.runtime.object.PFactory; -import com.oracle.truffle.api.CompilerDirectives; import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary; import com.oracle.truffle.api.dsl.Bind; import com.oracle.truffle.api.dsl.Cached; @@ -172,7 +167,6 @@ public void postInitialize(Python3Core core) { PythonLanguage language = core.getLanguage(); PythonModule self = core.lookupBuiltinModule(T_HASHLIB); EconomicMapStorage storage = EconomicMapStorage.create(); - LazyBouncyCastleProvider.initProvider(); ArrayList digests = new ArrayList<>(); for (var provider : Security.getProviders()) { for (var service : provider.getServices()) { @@ -399,12 +393,29 @@ static Object doIt(VirtualFrame frame, Node inliningTarget, PythonBuiltinClassTy @TruffleBoundary private static MessageDigest createDigest(String name, byte[] bytes, int bytesLen) throws NoSuchAlgorithmException { - MessageDigest digest = MessageDigest.getInstance(name); + MessageDigest digest; + try { + digest = MessageDigest.getInstance(name); + } catch (NoSuchAlgorithmException primary) { + if (!isBouncyCastleDigest(name)) { + throw primary; + } + try { + digest = BouncyCastleSupportProvider.createDigest(name); + } catch (NoSuchAlgorithmException secondary) { + primary.addSuppressed(secondary); + throw primary; + } + } if (bytes != null) { digest.update(bytes, 0, bytesLen); } return digest; } + + private static boolean isBouncyCastleDigest(String name) { + return name.startsWith("BLAKE2B-") || name.startsWith("BLAKE2S-"); + } } @Builtin(name = "new", minNumOfPositionalArgs = 1, parameterNames = {"name", "string"}, keywordOnlyNames = {"usedforsecurity"}) @@ -481,10 +492,7 @@ static Object pbkdf2(VirtualFrame frame, TruffleString hashName, Object password @Cached TruffleString.ToJavaStringNode toJavaStringNode, @Cached PRaiseNode raiseNode) { try { - Digest digest = getDigest(toJavaStringNode.execute(hashName)); - if (digest == null) { - throw raiseNode.raise(inliningTarget, PythonBuiltinClassType.UnsupportedDigestmodError, UNSUPPORTED_HASH_TYPE, hashName); - } + String javaHashName = toJavaStringNode.execute(hashName); if (iterations < 1) { throw raiseNode.raise(inliningTarget, PythonBuiltinClassType.ValueError, ITERATION_VALUE_MUST_BE_GREATER_THAN_ZERO); } @@ -493,11 +501,10 @@ static Object pbkdf2(VirtualFrame frame, TruffleString hashName, Object password } long dklen; if (noDklenProfile.profile(inliningTarget, PGuards.isPNone(dklenObj))) { - dklen = digest.getDigestSize(); + dklen = getPbkdf2MacLength(javaHashName); } else { dklen = asLongNode.execute(frame, inliningTarget, dklenObj); } - dklen *= Byte.SIZE; if (dklen < 1) { throw raiseNode.raise(inliningTarget, PythonBuiltinClassType.ValueError, KEY_LENGTH_MUST_BE_GREATER_THAN_ZERO); } @@ -506,7 +513,9 @@ static Object pbkdf2(VirtualFrame frame, TruffleString hashName, Object password } byte[] passwordBytes = passwordLib.getInternalOrCopiedExactByteArray(password); byte[] saltBytes = saltLib.getInternalOrCopiedExactByteArray(salt); - return PFactory.createBytes(language, generate(digest, passwordBytes, saltBytes, (int) iterations, (int) dklen)); + return PFactory.createBytes(language, generate(javaHashName, passwordBytes, saltBytes, (int) iterations, (int) dklen)); + } catch (GeneralSecurityException e) { + throw raiseNode.raise(inliningTarget, PythonBuiltinClassType.UnsupportedDigestmodError, UNSUPPORTED_HASH_TYPE, hashName); } finally { passwordLib.release(password); saltLib.release(salt); @@ -514,20 +523,70 @@ static Object pbkdf2(VirtualFrame frame, TruffleString hashName, Object password } @TruffleBoundary - private static Digest getDigest(String name) { - name = name.toLowerCase(); - return DigestFactory.getDigest(NAME_MAPPINGS.getOrDefault(name, name)); + private static int getPbkdf2MacLength(String name) throws NoSuchAlgorithmException { + return switch (name.toLowerCase()) { + case "sha1" -> 20; + case "sha224" -> 28; + case "sha256" -> 32; + case "sha384" -> 48; + case "sha512" -> 64; + default -> throw new NoSuchAlgorithmException(name); + }; } @TruffleBoundary - private static byte[] generate(Digest digest, byte[] password, byte[] salt, int iterations, int dklen) { - PKCS5S2ParametersGenerator generator = new PKCS5S2ParametersGenerator(digest); - generator.init(password, salt, iterations); - CipherParameters cipherParameters = generator.generateDerivedParameters(dklen); - if (!(cipherParameters instanceof KeyParameter keyParameter)) { - throw CompilerDirectives.shouldNotReachHere("unexpected cipher parameters"); + private static Mac createPbkdf2Mac(String name) throws NoSuchAlgorithmException { + String algorithm = getPbkdf2Algorithm(name); + if (algorithm == null) { + throw new NoSuchAlgorithmException(name); + } + return Mac.getInstance(algorithm); + } + + private static String getPbkdf2Algorithm(String name) { + return switch (name.toLowerCase()) { + case "sha1" -> "HmacSHA1"; + case "sha224" -> "HmacSHA224"; + case "sha256" -> "HmacSHA256"; + case "sha384" -> "HmacSHA384"; + case "sha512" -> "HmacSHA512"; + default -> null; + }; + } + + @TruffleBoundary + private static byte[] generate(String hashName, byte[] password, byte[] salt, int iterations, int dklen) throws GeneralSecurityException { + Mac mac = createPbkdf2Mac(hashName); + try { + String algorithm = mac.getAlgorithm(); + mac.init(new SecretKeySpec(password, algorithm)); + int digestLength = mac.getMacLength(); + byte[] derivedKey = new byte[dklen]; + byte[] block = new byte[digestLength]; + byte[] u = new byte[digestLength]; + byte[] blockIndex = new byte[Integer.BYTES]; + int blockCount = (dklen + digestLength - 1) / digestLength; + for (int i = 1; i <= blockCount; i++) { + ByteBuffer.wrap(blockIndex).putInt(i); + mac.update(salt); + mac.update(blockIndex); + byte[] initial = mac.doFinal(); + System.arraycopy(initial, 0, block, 0, digestLength); + System.arraycopy(initial, 0, u, 0, digestLength); + for (int j = 1; j < iterations; j++) { + u = mac.doFinal(u); + for (int k = 0; k < digestLength; k++) { + block[k] ^= u[k]; + } + } + int offset = (i - 1) * digestLength; + int length = Math.min(digestLength, dklen - offset); + System.arraycopy(block, 0, derivedKey, offset, length); + } + return derivedKey; + } catch (InvalidKeyException e) { + throw new IllegalStateException(e); } - return keyParameter.getKey(); } } } diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/ssl/CertUtils.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/ssl/CertUtils.java index 7cffee1acc..98eca6f85d 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/ssl/CertUtils.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/ssl/CertUtils.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2021, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * The Universal Permissive License (UPL), Version 1.0 @@ -61,12 +61,15 @@ import java.io.ByteArrayInputStream; import java.io.IOException; import java.math.BigInteger; +import java.security.GeneralSecurityException; import java.security.InvalidKeyException; +import java.security.KeyFactory; import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; import java.security.NoSuchProviderException; import java.security.PrivateKey; import java.security.Provider; +import java.security.Security; import java.security.PublicKey; import java.security.Signature; import java.security.SignatureException; @@ -76,29 +79,26 @@ import java.security.cert.CertificateFactory; import java.security.cert.CertificateParsingException; import java.security.cert.X509Certificate; +import java.security.spec.InvalidKeySpecException; +import java.security.spec.PKCS8EncodedKeySpec; +import java.security.spec.RSAPrivateCrtKeySpec; import java.time.ZoneId; import java.time.ZonedDateTime; import java.time.format.DateTimeFormatter; import java.util.ArrayList; import java.util.Arrays; +import java.util.Base64; import java.util.Collection; import java.util.Collections; import java.util.Date; +import java.util.LinkedHashMap; import java.util.List; +import java.util.Map; -import org.bouncycastle.asn1.pkcs.PrivateKeyInfo; -import org.bouncycastle.cert.X509CRLHolder; -import org.bouncycastle.cert.X509CertificateHolder; -import org.bouncycastle.openssl.PEMEncryptedKeyPair; -import org.bouncycastle.openssl.PEMKeyPair; -import org.bouncycastle.openssl.PEMParser; -import org.bouncycastle.openssl.jcajce.JcaPEMKeyConverter; -import org.bouncycastle.openssl.jcajce.JceOpenSSLPKCS8DecryptorProviderBuilder; -import org.bouncycastle.openssl.jcajce.JcePEMDecryptorProviderBuilder; -import org.bouncycastle.operator.OperatorCreationException; -import org.bouncycastle.pkcs.PKCS8EncryptedPrivateKeyInfo; -import org.bouncycastle.pkcs.PKCSException; -import org.bouncycastle.util.encoders.DecoderException; +import javax.crypto.EncryptedPrivateKeyInfo; +import javax.crypto.SecretKey; +import javax.crypto.SecretKeyFactory; +import javax.crypto.spec.PBEKeySpec; import com.oracle.graal.python.PythonLanguage; import com.oracle.graal.python.builtins.objects.common.HashingStorage; @@ -108,6 +108,7 @@ import com.oracle.graal.python.nodes.ErrorMessages; import com.oracle.graal.python.nodes.PConstructAndRaiseNode; import com.oracle.graal.python.runtime.PythonContext; +import com.oracle.graal.python.runtime.crypto.BouncyCastleSupportProvider; import com.oracle.graal.python.runtime.object.PFactory; import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary; import com.oracle.truffle.api.TruffleFile; @@ -142,6 +143,23 @@ public NeedsPasswordException() { } } + public static final class BadBase64Exception extends IOException { + private static final long serialVersionUID = -8554489203372180057L; + + public BadBase64Exception(Throwable cause) { + super(cause); + } + } + + private record PemBlock(String type, byte[] content) { + } + + private record KeyPemBlock(String type, byte[] content, Map headers) { + } + + private record PemBlockWithContent(String type, String content, int nextIndex) { + } + /** * openssl v3_purp.c#check_ca */ @@ -315,6 +333,7 @@ private static PTuple parseSubjectAltName(X509Certificate certificate, PythonLan // private static private static final class DerValue { + private static final byte INTEGER = 0x02; private static final byte OCTET_STRING = 0x04; private static final byte OBJECT_IDENTIFIER = 0x06; private static final byte SEQUENCE = 0x10; @@ -380,6 +399,31 @@ byte[] getRawData() { return Arrays.copyOfRange(data, contentStart, contentStart + contentLen); } + BigInteger getInteger() throws CertificateParsingException { + if (contentTag != INTEGER) { + throw new CertificateParsingException(ERROR_MESSAGE); + } + return new BigInteger(getRawData()); + } + + List getSequenceElements() throws CertificateParsingException { + if (contentTag != SEQUENCE) { + throw new CertificateParsingException(ERROR_MESSAGE); + } + ArrayList values = new ArrayList<>(); + int offset = contentStart; + int end = contentStart + contentLen; + while (offset < end) { + DerValue value = new DerValue(data, offset, end); + values.add(value); + offset = value.contentStart + value.contentLen; + } + if (offset != end) { + throw new CertificateParsingException(ERROR_MESSAGE); + } + return values; + } + DerValue getObjectIdentifier() throws CertificateParsingException { if (contentTag != OBJECT_IDENTIFIER) { return null; @@ -431,14 +475,6 @@ String getGeneralNameURI() { } } - List getSequenceElements() throws CertificateParsingException { - List result = new ArrayList<>(); - iterateSequence((e, r) -> { - result.add(e); - }, result); - return result; - } - @FunctionalInterface private interface DerSequenceConsumer { abstract void accept(A a, B b) throws CertificateParsingException; @@ -609,61 +645,124 @@ public static List getCertificates(BufferedReader r) throws IOException, @TruffleBoundary public static List getCertificates(BufferedReader r, boolean onlyCertificates) throws IOException, CertificateException, CRLException { List l = new ArrayList<>(); - PEMParser pemParser = new PEMParser(r); CertificateFactory factory = CertificateFactory.getInstance("X.509"); - Object object; - while ((object = pemParser.readObject()) != null) { - if (object instanceof X509CertificateHolder) { - // TODO use the X509CertificateHolder directly without conversion - l.add(factory.generateCertificate(new ByteArrayInputStream(((X509CertificateHolder) object).getEncoded()))); - } - if (!onlyCertificates && object instanceof X509CRLHolder) { - // TODO use the X509CRLHolder directly without conversion - l.add(factory.generateCRL(new ByteArrayInputStream(((X509CRLHolder) object).getEncoded()))); + for (PemBlock block : readPemBlocks(r)) { + if ("CERTIFICATE".equals(block.type())) { + l.add(factory.generateCertificate(new ByteArrayInputStream(block.content()))); + } else if (!onlyCertificates && ("X509 CRL".equals(block.type()) || "CRL".equals(block.type()))) { + l.add(factory.generateCRL(new ByteArrayInputStream(block.content()))); } } return l; } + private static List readPemBlocks(BufferedReader reader) throws IOException { + StringBuilder text = new StringBuilder(); + char[] buffer = new char[8192]; + int read; + while ((read = reader.read(buffer)) != -1) { + text.append(buffer, 0, read); + } + + String data = text.toString(); + List blocks = new ArrayList<>(); + int fromIndex = 0; + while (true) { + int begin = data.indexOf("-----BEGIN ", fromIndex); + if (begin < 0) { + return blocks; + } + int typeStart = begin + "-----BEGIN ".length(); + int typeEnd = data.indexOf("-----", typeStart); + if (typeEnd < 0) { + throw new IOException("Malformed PEM header"); + } + String type = data.substring(typeStart, typeEnd); + int contentStart = typeEnd + "-----".length(); + if (contentStart < data.length() && data.charAt(contentStart) == '\r') { + contentStart++; + } + if (contentStart < data.length() && data.charAt(contentStart) == '\n') { + contentStart++; + } + + String endMarker = "-----END " + type + "-----"; + int end = data.indexOf(endMarker, contentStart); + if (end < 0) { + throw new IOException("Missing PEM footer"); + } + + String content = data.substring(contentStart, end); + if (isCertificatePemType(type)) { + blocks.add(new PemBlock(type, decodePemContent(content))); + } + fromIndex = end + endMarker.length(); + } + } + + private static boolean isCertificatePemType(String type) { + return "CERTIFICATE".equals(type) || "X509 CRL".equals(type) || "CRL".equals(type); + } + + private static byte[] decodePemContent(String content) throws IOException { + StringBuilder base64 = new StringBuilder(content.length()); + for (String line : content.split("\\R")) { + String trimmed = line.trim(); + if (trimmed.isEmpty()) { + continue; + } + if (trimmed.indexOf(':') >= 0) { + throw new IOException("Unexpected PEM headers"); + } + base64.append(trimmed); + } + if (base64.length() == 0) { + throw new IOException("Empty PEM content"); + } + try { + return Base64.getMimeDecoder().decode(base64.toString()); + } catch (IllegalArgumentException e) { + throw new BadBase64Exception(e); + } + } + // No BoundaryCallContext: constructs and raises only builtin errors @TruffleBoundary static PrivateKey getPrivateKey(PythonContext context, Node inliningTarget, PConstructAndRaiseNode.Lazy raiseNode, BufferedReader reader, char[] password, X509Certificate cert) throws NeedsPasswordException { - PEMParser pemParser = new PEMParser(reader); - JcaPEMKeyConverter converter = new JcaPEMKeyConverter(); - Provider provider = LazyBouncyCastleProvider.initProvider(); - converter.setProvider(provider); PrivateKey privateKey = null; + String algorithm = cert.getPublicKey().getAlgorithm(); try { - Object object; - while ((object = pemParser.readObject()) != null) { - PrivateKeyInfo pkInfo; - if (object instanceof PEMKeyPair) { - pkInfo = ((PEMKeyPair) object).getPrivateKeyInfo(); - } else if (object instanceof PEMEncryptedKeyPair) { + String pemText = reader.readAllAsString(); + int fromIndex = 0; + PemBlockWithContent rawBlock; + while ((rawBlock = findNextPemBlock(pemText, fromIndex)) != null) { + fromIndex = rawBlock.nextIndex(); + KeyPemBlock block = decodePrivateKeyPemBlock(rawBlock.type(), rawBlock.content()); + if ("PRIVATE KEY".equals(block.type())) { + privateKey = decodePrivateKey(algorithm, block.content()); + break; + } else if ("ENCRYPTED PRIVATE KEY".equals(block.type())) { if (password == null) { throw new NeedsPasswordException(); } - JcePEMDecryptorProviderBuilder decryptor = new JcePEMDecryptorProviderBuilder(); - decryptor.setProvider(provider); - PEMKeyPair keyPair = ((PEMEncryptedKeyPair) object).decryptKeyPair(decryptor.build(password)); - pkInfo = keyPair.getPrivateKeyInfo(); - } else if (object instanceof PKCS8EncryptedPrivateKeyInfo) { - if (password == null) { - throw new NeedsPasswordException(); + privateKey = decodeEncryptedPrivateKey(algorithm, block.content(), password); + break; + } else if (isLegacyPrivateKeyType(block.type())) { + if ("RSA PRIVATE KEY".equals(block.type()) && block.headers().isEmpty()) { + privateKey = decodeRsaPrivateKey(block.content()); + } else { + if (!block.headers().isEmpty() && password == null) { + throw new NeedsPasswordException(); + } + privateKey = BouncyCastleSupportProvider.loadPrivateKey(password, pemBlockToText(rawBlock)); } - JceOpenSSLPKCS8DecryptorProviderBuilder decryptor = new JceOpenSSLPKCS8DecryptorProviderBuilder(); - decryptor.setProvider(provider); - pkInfo = ((PKCS8EncryptedPrivateKeyInfo) object).decryptPrivateKeyInfo(decryptor.build(password)); - } else if (object instanceof PrivateKeyInfo) { - pkInfo = (PrivateKeyInfo) object; - } else { - continue; + break; } - privateKey = converter.getPrivateKey(pkInfo); - break; } - } catch (IOException | DecoderException | OperatorCreationException | PKCSException e) { + } catch (BouncyCastleSupportProvider.MissingBouncyCastleException e) { + throw raiseNode.get(inliningTarget).raiseSSLError(null, SSLErrorCode.ERROR_SSL, toTruffleStringUncached(e.getMessage())); + } catch (IOException | GeneralSecurityException e) { throw raiseNode.get(inliningTarget).raiseSSLError(null, SSLErrorCode.ERROR_SSL_PEM_LIB, ErrorMessages.SSL_PEM_LIB); } if (privateKey == null) { @@ -674,36 +773,204 @@ static PrivateKey getPrivateKey(PythonContext context, Node inliningTarget, PCon return privateKey; } + private static PemBlockWithContent findNextPemBlock(String data, int fromIndex) throws IOException { + int begin = data.indexOf("-----BEGIN ", fromIndex); + if (begin < 0) { + return null; + } + int typeStart = begin + "-----BEGIN ".length(); + int typeEnd = data.indexOf("-----", typeStart); + if (typeEnd < 0) { + throw new IOException("Malformed PEM header"); + } + String type = data.substring(typeStart, typeEnd); + int contentStart = typeEnd + "-----".length(); + if (contentStart < data.length() && data.charAt(contentStart) == '\r') { + contentStart++; + } + if (contentStart < data.length() && data.charAt(contentStart) == '\n') { + contentStart++; + } + String endMarker = "-----END " + type + "-----"; + int end = data.indexOf(endMarker, contentStart); + if (end < 0) { + throw new IOException("Missing PEM footer"); + } + return new PemBlockWithContent(type, data.substring(contentStart, end), end + endMarker.length()); + } + + private static KeyPemBlock decodePrivateKeyPemBlock(String type, String content) throws IOException { + Map headers = new LinkedHashMap<>(); + StringBuilder base64 = new StringBuilder(content.length()); + boolean seenBase64 = false; + for (String line : content.split("\\R")) { + String trimmed = line.trim(); + if (trimmed.isEmpty()) { + continue; + } + int colon = trimmed.indexOf(':'); + if (!seenBase64 && colon >= 0) { + headers.put(trimmed.substring(0, colon).trim(), trimmed.substring(colon + 1).trim()); + } else { + if (colon >= 0) { + throw new IOException("Malformed PEM content"); + } + seenBase64 = true; + base64.append(trimmed); + } + } + if (base64.length() == 0) { + throw new IOException("Empty PEM content"); + } + try { + return new KeyPemBlock(type, Base64.getMimeDecoder().decode(base64.toString()), headers); + } catch (IllegalArgumentException e) { + throw new BadBase64Exception(e); + } + } + + private static boolean isLegacyPrivateKeyType(String type) { + return "RSA PRIVATE KEY".equals(type) || "DSA PRIVATE KEY".equals(type) || "EC PRIVATE KEY".equals(type); + } + + private static String pemBlockToText(PemBlockWithContent block) { + return "-----BEGIN " + block.type() + "-----\n" + block.content() + "\n-----END " + block.type() + "-----\n"; + } + + private static PrivateKey decodePrivateKey(String algorithm, byte[] encoded) throws NoSuchAlgorithmException, InvalidKeySpecException { + return getKeyFactory(algorithm).generatePrivate(new PKCS8EncodedKeySpec(encoded)); + } + + private static PrivateKey decodeEncryptedPrivateKey(String algorithm, byte[] encoded, char[] password) throws IOException, GeneralSecurityException { + EncryptedPrivateKeyInfo encryptedPrivateKeyInfo = new EncryptedPrivateKeyInfo(encoded); + SecretKeyFactory secretKeyFactory = getSecretKeyFactory(encryptedPrivateKeyInfo.getAlgName()); + SecretKey secretKey = secretKeyFactory.generateSecret(new PBEKeySpec(password)); + Provider provider = getPreferredSecurityProvider(); + PKCS8EncodedKeySpec keySpec = provider != null ? encryptedPrivateKeyInfo.getKeySpec(secretKey, provider) : encryptedPrivateKeyInfo.getKeySpec(secretKey); + return getKeyFactory(algorithm).generatePrivate(keySpec); + } + + private static PrivateKey decodeRsaPrivateKey(byte[] encoded) throws InvalidKeySpecException, NoSuchAlgorithmException { + try { + DerValue sequence = new DerValue(encoded); + List values = sequence.getSequenceElements(); + if (values.size() < 9) { + throw new InvalidKeySpecException("Invalid RSA private key"); + } + BigInteger version = values.get(0).getInteger(); + if (!BigInteger.ZERO.equals(version) && !BigInteger.ONE.equals(version)) { + throw new InvalidKeySpecException("Unsupported RSA private key version"); + } + RSAPrivateCrtKeySpec keySpec = new RSAPrivateCrtKeySpec( + values.get(1).getInteger(), + values.get(2).getInteger(), + values.get(3).getInteger(), + values.get(4).getInteger(), + values.get(5).getInteger(), + values.get(6).getInteger(), + values.get(7).getInteger(), + values.get(8).getInteger()); + return getKeyFactory("RSA").generatePrivate(keySpec); + } catch (CertificateParsingException e) { + throw new InvalidKeySpecException("Invalid RSA private key", e); + } + } + + private static KeyFactory getKeyFactory(String algorithm) throws NoSuchAlgorithmException { + Provider provider = getPreferredSecurityProvider(); + return provider != null ? KeyFactory.getInstance(algorithm, provider) : KeyFactory.getInstance(algorithm); + } + + private static SecretKeyFactory getSecretKeyFactory(String algorithm) throws NoSuchAlgorithmException { + Provider provider = getPreferredSecurityProvider(); + return provider != null ? SecretKeyFactory.getInstance(algorithm, provider) : SecretKeyFactory.getInstance(algorithm); + } + + private static Provider getPreferredSecurityProvider() { + String providerName = System.getProperty("python.security.provider"); + if (providerName == null || providerName.isEmpty()) { + return null; + } + return Security.getProvider(providerName); + } + private static void checkPrivateKey(Node inliningTarget, PConstructAndRaiseNode.Lazy raiseNode, PythonContext context, PrivateKey privateKey, PublicKey publicKey) { /* * Check that the private key matches the public key by signing and verifying a short piece * of data. */ + byte[] data = new byte[128]; + context.getSecureRandom().nextBytes(data); try { - Signature sign; + String signatureAlgorithm = privateKey.getAlgorithm(); + if ("EC".equals(signatureAlgorithm)) { + signatureAlgorithm = "ECDSA"; + } try { - sign = Signature.getInstance(String.format("SHA256with%s", privateKey.getAlgorithm())); + if (checkPrivateKey("SHA256with%s".formatted(signatureAlgorithm), privateKey, publicKey, data)) { + return; + } } catch (NoSuchAlgorithmException e) { - sign = Signature.getInstance(String.format("SHA1with%s", privateKey.getAlgorithm())); - } - sign.initSign(privateKey); - byte[] data = new byte[128]; - context.getSecureRandom().nextBytes(data); - sign.update(data); - byte[] signature = sign.sign(); - sign.initVerify(publicKey); - sign.update(data); - if (sign.verify(signature)) { - return; + if (checkPrivateKey("SHA1with%s".formatted(signatureAlgorithm), privateKey, publicKey, data)) { + return; + } } } catch (NoSuchAlgorithmException e) { throw raiseNode.get(inliningTarget).raiseSSLError(null, SSLErrorCode.ERROR_SSL, e); - } catch (SignatureException | InvalidKeyException e) { + } catch (SignatureException e) { // fallthrough } throw raiseNode.get(inliningTarget).raiseSSLError(null, SSLErrorCode.ERROR_KEY_VALUES_MISMATCH, ErrorMessages.KEY_VALUES_MISMATCH); } + private static boolean checkPrivateKey(String signatureAlgorithm, PrivateKey privateKey, PublicKey publicKey, byte[] data) throws NoSuchAlgorithmException, SignatureException { + Provider preferredProvider = getPreferredSecurityProvider(); + if (preferredProvider != null && checkPrivateKey(signatureAlgorithm, preferredProvider, privateKey, publicKey, data)) { + return true; + } + Provider[] providers = Security.getProviders("Signature." + signatureAlgorithm); + if (providers != null) { + for (Provider provider : providers) { + if ((preferredProvider == null || !preferredProvider.getName().equals(provider.getName())) && checkPrivateKey(signatureAlgorithm, provider, privateKey, publicKey, data)) { + return true; + } + } + } + if (checkPrivateKeyWithBouncyCastle(signatureAlgorithm, privateKey, publicKey, data)) { + return true; + } + return checkPrivateKey(signatureAlgorithm, (Provider) null, privateKey, publicKey, data); + } + + private static boolean checkPrivateKey(String signatureAlgorithm, Provider provider, PrivateKey privateKey, PublicKey publicKey, byte[] data) throws NoSuchAlgorithmException, SignatureException { + try { + Signature signature = provider != null ? Signature.getInstance(signatureAlgorithm, provider) : Signature.getInstance(signatureAlgorithm); + signature.initSign(privateKey); + signature.update(data); + byte[] signed = signature.sign(); + signature.initVerify(publicKey); + signature.update(data); + boolean verified = signature.verify(signed); + return verified; + } catch (InvalidKeyException e) { + return false; + } + } + + private static boolean checkPrivateKeyWithBouncyCastle(String signatureAlgorithm, PrivateKey privateKey, PublicKey publicKey, byte[] data) throws NoSuchAlgorithmException, SignatureException { + try { + Signature signature = BouncyCastleSupportProvider.createSignature(signatureAlgorithm); + signature.initSign(privateKey); + signature.update(data); + byte[] signed = signature.sign(); + signature.initVerify(publicKey); + signature.update(data); + return signature.verify(signed); + } catch (InvalidKeyException e) { + return false; + } + } + @TruffleBoundary static Collection generateCertificates(byte[] bytes) throws CertificateException { // test_load_verify_cadata appends an extra byte to a valid certificate and expects diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/ssl/SSLCipherSelector.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/ssl/SSLCipherSelector.java index 341a460e0f..506c496a2a 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/ssl/SSLCipherSelector.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/ssl/SSLCipherSelector.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2021, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * The Universal Permissive License (UPL), Version 1.0 @@ -118,7 +118,7 @@ private static void selectSingle(Node node, String cipherString, List if (cipherString.startsWith("@STRENGTH")) { selected.sort(Comparator.comparingInt(SSLCipher::getStrengthBits).reversed()); } else if (cipherString.startsWith("@SECLEVEL=")) { - throw PRaiseNode.raiseStatic(node, NotImplementedError, toTruffleStringUncached("@SECLEVEL not implemented")); + handleSecurityLevel(node, cipherString); } else { EncapsulatingNodeReference nodeRef = EncapsulatingNodeReference.getCurrent(); Node prev = nodeRef.set(node); @@ -140,6 +140,34 @@ private static void selectSingle(Node node, String cipherString, List } } + private static void handleSecurityLevel(Node node, String cipherString) { + String levelString = cipherString.substring("@SECLEVEL=".length()); + if ("1".equals(levelString)) { + return; + } + if (!isDecimalDigits(levelString)) { + throw PRaiseNode.raiseStatic(node, + NotImplementedError, + toTruffleStringUncached("Unsupported OpenSSL cipher string directive: " + cipherString)); + } + throw PRaiseNode.raiseStatic(node, + NotImplementedError, + toTruffleStringUncached("Unsupported OpenSSL security level @SECLEVEL=" + levelString + "; only @SECLEVEL=1 is supported")); + } + + private static boolean isDecimalDigits(String value) { + if (value.isEmpty()) { + return false; + } + for (int i = 0; i < value.length(); i++) { + char ch = value.charAt(i); + if (ch < '0' || ch > '9') { + return false; + } + } + return true; + } + private static List getCiphersForCipherString(Node node, String cipherString) { List result = null; for (String component : cipherString.split("\\+")) { diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/ssl/SSLContextBuiltins.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/ssl/SSLContextBuiltins.java index 21df03c257..d1f6df16fc 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/ssl/SSLContextBuiltins.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/ssl/SSLContextBuiltins.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2021, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * The Universal Permissive License (UPL), Version 1.0 @@ -76,7 +76,7 @@ import javax.net.ssl.SSLEngine; import javax.net.ssl.SSLParameters; -import org.bouncycastle.util.encoders.DecoderException; +import com.oracle.graal.python.builtins.objects.ssl.CertUtils.BadBase64Exception; import com.oracle.graal.python.PythonLanguage; import com.oracle.graal.python.annotations.ArgumentClinic; @@ -637,7 +637,7 @@ private void setBoundary(PSSLContext self, PyUnicodeFSDecoderNode asPath) { LOGGER.fine(() -> String.format("set_default_verify_paths file: %s. path: %s", file != null ? file.getPath() : "None", path != null ? path.getPath() : "None")); try { self.setCAEntries(CertUtils.loadVerifyLocations(file, path)); - } catch (IOException | DecoderException | GeneralSecurityException | NoCertificateFoundException ex) { + } catch (IOException | GeneralSecurityException | NoCertificateFoundException ex) { // do not raise any errors LOGGER.log(Level.FINER, "", ex); } @@ -756,7 +756,7 @@ Object load(VirtualFrame frame, PSSLContext self, Object cafile, Object capath, self.setCAEntries(CertUtils.loadVerifyLocations(file, path)); } catch (NoCertificateFoundException e) { throw constructAndRaiseNode.get(inliningTarget).raiseSSLError(frame, SSLErrorCode.ERROR_NO_CERTIFICATE_OR_CRL_FOUND, ErrorMessages.NO_CERTIFICATE_OR_CRL_FOUND); - } catch (IOException | DecoderException e) { + } catch (IOException | CertificateException | CRLException e) { throw constructAndRaiseNode.get(inliningTarget).raiseSSLError(frame, SSLErrorCode.ERROR_SSL_PEM_LIB, ErrorMessages.X509_PEM_LIB); } } @@ -792,9 +792,9 @@ private static List getCertificates(Node inliningTarget, PConstructAndRa throw raiseNode.get(inliningTarget).raiseSSLError(null, SSLErrorCode.ERROR_NO_START_LINE, ErrorMessages.SSL_PEM_NO_START_LINE); } return certificates; - } catch (DecoderException e) { + } catch (BadBase64Exception e) { throw raiseNode.get(inliningTarget).raiseSSLError(null, SSLErrorCode.ERROR_BAD_BASE64_DECODE, ErrorMessages.BAD_BASE64_DECODE); - } catch (IOException e) { + } catch (IOException | CertificateException | CRLException e) { throw raiseNode.get(inliningTarget).raiseSSLError(null, SSLErrorCode.ERROR_SSL_PEM_LIB, ErrorMessages.SSL_PEM_LIB); } } @@ -889,7 +889,7 @@ private static Object load(PythonContext context, Node inliningTarget, PConstruc if (certs.length == 0) { throw raiseNode.get(inliningTarget).raiseSSLError(null, SSLErrorCode.ERROR_SSL_PEM_LIB, ErrorMessages.SSL_PEM_LIB); } - } catch (IOException | DecoderException e) { + } catch (IOException | CertificateException | CRLException e) { throw raiseNode.get(inliningTarget).raiseSSLError(null, SSLErrorCode.ERROR_SSL_PEM_LIB, ErrorMessages.SSL_PEM_LIB); } // if keyReader and certReader are from the same file, key is expected to come first diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/ssl/SSLOperationNode.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/ssl/SSLOperationNode.java index 6a0b34fbf8..e871e14fac 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/ssl/SSLOperationNode.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/ssl/SSLOperationNode.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2021, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * The Universal Permissive License (UPL), Version 1.0 @@ -554,6 +554,10 @@ private static PException handleSSLException(Node inliningTarget, SSLException e if (e.getCause() instanceof CertificateException) { throw raiseNode.get(inliningTarget).raiseSSLError(null, SSLErrorCode.ERROR_CERT_VERIFICATION, ErrorMessages.CERTIFICATE_VERIFY_FAILED, e.toString()); } - throw raiseNode.get(inliningTarget).raiseSSLError(null, SSLErrorCode.ERROR_SSL, toTruffleStringUncached(e.toString())); + String message = e.toString(); + if (message.contains("Unrecognized SSL message, plaintext connection?")) { + message = "before TLS handshake with data"; + } + throw raiseNode.get(inliningTarget).raiseSSLError(null, SSLErrorCode.ERROR_SSL, toTruffleStringUncached(message)); } } diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/runtime/PythonCryptoFeature.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/runtime/PythonCryptoFeature.java new file mode 100644 index 0000000000..8f0bb49409 --- /dev/null +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/runtime/PythonCryptoFeature.java @@ -0,0 +1,104 @@ +/* + * Copyright (c) 2022, 2026, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * The Universal Permissive License (UPL), Version 1.0 + * + * Subject to the condition set forth below, permission is hereby granted to any + * person obtaining a copy of this software, associated documentation and/or + * data (collectively the "Software"), free of charge and under any and all + * copyright rights in the Software, and any and all patent rights owned or + * freely licensable by each licensor hereunder covering either (i) the + * unmodified Software as contributed to or provided by such licensor, or (ii) + * the Larger Works (as defined below), to deal in both + * + * (a) the Software, and + * + * (b) any piece of software and/or hardware listed in the lrgrwrks.txt file if + * one is included with the Software each a "Larger Work" to which the Software + * is contributed by such licensors), + * + * without restriction, including without limitation the rights to copy, create + * derivative works of, display, perform, and distribute the Software and make, + * use, sell, offer for sale, import, export, have made, and have sold the + * Software and the Larger Work(s), and to sublicense the foregoing rights on + * either these or other terms. + * + * This license is subject to the following condition: + * + * The above copyright notice and either this complete permission notice or at a + * minimum a reference to the UPL must be included in all copies or substantial + * portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ +package com.oracle.graal.python.runtime; + +import java.io.IOException; +import java.io.InputStream; +import java.security.Security; + +import org.graalvm.nativeimage.hosted.Feature; +import org.graalvm.nativeimage.hosted.RuntimeReflection; +import org.graalvm.nativeimage.hosted.RuntimeResourceAccess; + +public final class PythonCryptoFeature implements Feature { + + private static final String[] HKDF_REFLECTIVE_CLASSES = { + "com.sun.crypto.provider.HKDFKeyDerivation$HKDFSHA256", + "com.sun.crypto.provider.HKDFKeyDerivation$HKDFSHA384", + "com.sun.crypto.provider.HKDFKeyDerivation$HKDFSHA512", + "sun.security.pkcs11.P11HKDF", + }; + private static final String BC_SUPPORT_CLASS = "com.oracle.graal.python.bouncycastle.BouncyCastleSupportImpl"; + private static final String BC_SUPPORT_SERVICE_RESOURCE = "META-INF/services/com.oracle.graal.python.runtime.crypto.BouncyCastleSupport"; + + @Override + public void afterRegistration(AfterRegistrationAccess access) { + registerHkdfReflection(); + registerOptionalBouncyCastleSupport(); + } + + private static void registerHkdfReflection() { + for (String name : HKDF_REFLECTIVE_CLASSES) { + try { + Class.forName(name); + } catch (SecurityException | ClassNotFoundException e) { + return; + } + } + Security.addProvider(Security.getProvider("SunJCE")); + for (String name : HKDF_REFLECTIVE_CLASSES) { + try { + Class clazz = Class.forName(name); + RuntimeReflection.register(clazz); + RuntimeReflection.register(clazz.getConstructors()); + } catch (SecurityException | ClassNotFoundException e) { + throw new RuntimeException("Could not register " + name + " for reflective access!", e); + } + } + } + + private static void registerOptionalBouncyCastleSupport() { + try { + Class clazz = Class.forName(BC_SUPPORT_CLASS); + RuntimeReflection.register(clazz); + RuntimeReflection.register(clazz.getConstructors()); + try (InputStream stream = clazz.getClassLoader().getResourceAsStream(BC_SUPPORT_SERVICE_RESOURCE)) { + if (stream != null) { + RuntimeResourceAccess.addResource(clazz.getModule(), BC_SUPPORT_SERVICE_RESOURCE, stream.readAllBytes()); + } + } + } catch (ClassNotFoundException e) { + return; + } catch (SecurityException | IOException e) { + throw new RuntimeException("Could not register optional BouncyCastle support for native image.", e); + } + } +} diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/ssl/LazyBouncyCastleProvider.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/runtime/crypto/BouncyCastleSupport.java similarity index 72% rename from graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/ssl/LazyBouncyCastleProvider.java rename to graalpython/com.oracle.graal.python/src/com/oracle/graal/python/runtime/crypto/BouncyCastleSupport.java index a4e15fc0d1..3db586ef22 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/ssl/LazyBouncyCastleProvider.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/runtime/crypto/BouncyCastleSupport.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * The Universal Permissive License (UPL), Version 1.0 @@ -38,21 +38,21 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * SOFTWARE. */ -package com.oracle.graal.python.builtins.objects.ssl; +package com.oracle.graal.python.runtime.crypto; -import java.security.Provider; -import java.security.Security; +import java.io.IOException; +import java.security.GeneralSecurityException; +import java.security.MessageDigest; +import java.security.NoSuchAlgorithmException; +import java.security.PrivateKey; +import java.security.Signature; -import org.bouncycastle.jce.provider.BouncyCastleProvider; +import com.oracle.graal.python.builtins.objects.ssl.CertUtils.NeedsPasswordException; -public final class LazyBouncyCastleProvider { - private static Provider securityProvider; +public interface BouncyCastleSupport { + PrivateKey loadPrivateKey(char[] password, String pemText) throws IOException, NeedsPasswordException, GeneralSecurityException; - public static synchronized Provider initProvider() { - if (securityProvider == null) { - securityProvider = new BouncyCastleProvider(); - Security.addProvider(securityProvider); - } - return securityProvider; - } + MessageDigest createDigest(String algorithm) throws NoSuchAlgorithmException; + + Signature createSignature(String algorithm) throws NoSuchAlgorithmException; } diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/runtime/crypto/BouncyCastleSupportProvider.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/runtime/crypto/BouncyCastleSupportProvider.java new file mode 100644 index 0000000000..dc904d9af7 --- /dev/null +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/runtime/crypto/BouncyCastleSupportProvider.java @@ -0,0 +1,132 @@ +/* + * Copyright (c) 2026, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * The Universal Permissive License (UPL), Version 1.0 + * + * Subject to the condition set forth below, permission is hereby granted to any + * person obtaining a copy of this software, associated documentation and/or + * data (collectively the "Software"), free of charge and under any and all + * copyright rights in the Software, and any and all patent rights owned or + * freely licensable by each licensor hereunder covering either (i) the + * unmodified Software as contributed to or provided by such licensor, or (ii) + * the Larger Works (as defined below), to deal in both + * + * (a) the Software, and + * + * (b) any piece of software and/or hardware listed in the lrgrwrks.txt file if + * one is included with the Software each a "Larger Work" to which the Software + * is contributed by such licensors), + * + * without restriction, including without limitation the rights to copy, create + * derivative works of, display, perform, and distribute the Software and make, + * use, sell, offer for sale, import, export, have made, and have sold the + * Software and the Larger Work(s), and to sublicense the foregoing rights on + * either these or other terms. + * + * This license is subject to the following condition: + * + * The above copyright notice and either this complete permission notice or at a + * minimum a reference to the UPL must be included in all copies or substantial + * portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ +package com.oracle.graal.python.runtime.crypto; + +import java.io.IOException; +import java.security.GeneralSecurityException; +import java.security.MessageDigest; +import java.security.NoSuchAlgorithmException; +import java.security.PrivateKey; +import java.security.Signature; +import java.util.Iterator; +import java.util.ServiceConfigurationError; +import java.util.ServiceLoader; + +import com.oracle.graal.python.builtins.objects.ssl.CertUtils.NeedsPasswordException; + +public final class BouncyCastleSupportProvider { + public static final String MISSING_PRIVATE_KEY_MESSAGE = "Encrypted legacy PEM private keys require BouncyCastle support; add the GraalPy BC support module and BouncyCastle jars to the classpath or modulepath, or convert the key to PKCS#8."; + + private BouncyCastleSupportProvider() { + } + + public static PrivateKey loadPrivateKey(char[] password, String pemText) throws IOException, NeedsPasswordException, GeneralSecurityException { + return getSupport().loadPrivateKey(password, pemText); + } + + public static MessageDigest createDigest(String algorithm) throws NoSuchAlgorithmException { + try { + return getSupport().createDigest(algorithm); + } catch (MissingBouncyCastleException e) { + NoSuchAlgorithmException wrapped = new NoSuchAlgorithmException(algorithm + " MessageDigest not available"); + wrapped.initCause(e); + throw wrapped; + } + } + + public static Signature createSignature(String algorithm) throws NoSuchAlgorithmException { + try { + return getSupport().createSignature(algorithm); + } catch (MissingBouncyCastleException e) { + NoSuchAlgorithmException wrapped = new NoSuchAlgorithmException(algorithm + " Signature not available"); + wrapped.initCause(e); + throw wrapped; + } + } + + private static BouncyCastleSupport getSupport() throws MissingBouncyCastleException { + Throwable failure = null; + try { + BouncyCastleSupport support = getSupport(ServiceLoader.load(ModuleLayer.boot(), BouncyCastleSupport.class)); + if (support != null) { + return support; + } + } catch (ServiceConfigurationError | LinkageError e) { + failure = e; + } + try { + BouncyCastleSupport support = getSupport(ServiceLoader.load(BouncyCastleSupport.class)); + if (support != null) { + return support; + } + } catch (ServiceConfigurationError | LinkageError e) { + if (failure != null) { + e.addSuppressed(failure); + } + failure = e; + } + try { + BouncyCastleSupport support = getSupport(ServiceLoader.load(BouncyCastleSupport.class, BouncyCastleSupportProvider.class.getClassLoader())); + if (support != null) { + return support; + } + } catch (ServiceConfigurationError | LinkageError e) { + if (failure != null) { + e.addSuppressed(failure); + } + failure = e; + } + throw new MissingBouncyCastleException(failure); + } + + private static BouncyCastleSupport getSupport(ServiceLoader serviceLoader) { + Iterator iterator = serviceLoader.iterator(); + return iterator.hasNext() ? iterator.next() : null; + } + + public static final class MissingBouncyCastleException extends GeneralSecurityException { + private static final long serialVersionUID = 1L; + + MissingBouncyCastleException(Throwable cause) { + super(MISSING_PRIVATE_KEY_MESSAGE, cause); + } + } +} diff --git a/mx.graalpython/mx_graalpython.py b/mx.graalpython/mx_graalpython.py index c94f524966..0b5f451b7b 100644 --- a/mx.graalpython/mx_graalpython.py +++ b/mx.graalpython/mx_graalpython.py @@ -2231,6 +2231,7 @@ def bytecode_dsl_build_args(prefix=''): ], truffle_jars=[ 'graalpython:GRAALPYTHON', + 'graalpython:GRAALPYTHON_BOUNCYCASTLE', 'graalpython:BOUNCYCASTLE-PROVIDER', 'graalpython:BOUNCYCASTLE-PKIX', 'graalpython:BOUNCYCASTLE-UTIL', diff --git a/mx.graalpython/suite.py b/mx.graalpython/suite.py index 7a2d973fca..7546a5d707 100644 --- a/mx.graalpython/suite.py +++ b/mx.graalpython/suite.py @@ -110,32 +110,32 @@ "digest": "sha512:bd77164795b5cbfbe864f64021e67e37f39cb9aba9abdd894d53fbb6857abe074923808918d1dc3bb0706253e726b2b9704cd0c3bc744d70e220c7356fa4995e", }, "BOUNCYCASTLE-PROVIDER": { - "digest": "sha512:fb10c3c089921c8173ad285329f730e0e78de175d1b50b9bdd79c6a85a265af9b3331caa0c1ed57e5f47047319ce3b0f3bb5def0a3db9cccf2755cc95e145e52", - "sourceDigest": "sha512:7b06374b75040a1dba9419e17be29a155f01b14961521adcb8e980397b6ac7e2de55958e74ad41ba94766c4e992935abbd94fb964dbf806445a63a7346c0ae2e", + "digest": "sha512:e51cc843ca130ad4a15ff667360063bbb583af3f22e14193840a734da6665b470ba1855ce975f88a94ddd6419aa020d3a9966980bc1deb7514f92a7215d6e229", + "sourceDigest": "sha512:a2fe72266afcffce846dde5735d0fa28935942177375dd1c29bac819c1163f2da967e0b893d33d43868b6cdb8aa469e05fa460543d5448fa1e34155dcf86b0b7", "maven": { "groupId": "org.bouncycastle", "artifactId": "bcprov-jdk18on", - "version": "1.78.1", + "version": "1.83", }, "moduleName": "org.bouncycastle.provider", }, "BOUNCYCASTLE-PKIX": { - "digest": "sha512:d71a45844a7946b6a70315254e82a335d2df5e402b2d5a3b496fa69b355184338011b49c5f1c76026764a76f62f2bc140c25db2881bca91dde9677a25c6d587b", - "sourceDigest": "sha512:8508e9b26c60cc2fd3219d8ab0d3928891ecc42926e7c862c0fbf9940a4bcffe35c4a76c3934b33ed4311817dbf3b0b50068482f7c5f550261a50cc97879923a", + "digest": "sha512:9c67d990a56a5c448f9bb9edbb8b99dc15971e16de7e6f10c3eab129a1389eef4882c5a5d910ac4ddc27d44f7bc9fa4054c7f56dc031154c131bccc50ebd67b9", + "sourceDigest": "sha512:f24ad816393ed53d737db3c976ef37e4e009c2a366a1b97f80dace063320336ed1463b526eb6913cd1d462c2be18debd43ac1cab415639f900706e8e4fc13fe1", "maven": { "groupId": "org.bouncycastle", "artifactId": "bcpkix-jdk18on", - "version": "1.78.1", + "version": "1.83", }, "moduleName": "org.bouncycastle.pkix", }, "BOUNCYCASTLE-UTIL": { - "digest": "sha512:6a338c50d662993c9f00bba23f98443c923b9a95ff61dc653906f51857f8afaecc57a536bfaf6848ac8e7e9ce0a21f84ec068815853261268f97e951526bc766", - "sourceDigest": "sha512:852a1679a9c690f97c4ed175272b04ebedc89b9e4aa0322f32a799f619fd71602f89545fc02bb1093750ad7d796500fdd116203862ccecb3085af40aadcccea6", + "digest": "sha512:e19831d4afc0a709fd57694f33bfe3a8e881cba287c34fb076a44ef436e56e6bdf49299ca9525028a4de9bf5fadeaa254654d0e527855f1f5659c5a7be538576", + "sourceDigest": "sha512:bc4195692721827b41e21eaa14f9cf14dffe6f141ddfb8ac26d2a89f4ead3f1611671f8b6d39ec4be479c2ccf6e4bf33176123474f852910dc7dcc23485bd036", "maven": { "groupId": "org.bouncycastle", "artifactId": "bcutil-jdk18on", - "version": "1.78.1", + "version": "1.83", }, "moduleName": "org.bouncycastle.util", }, @@ -390,9 +390,6 @@ "truffle:TRUFFLE_XZ", "truffle:TRUFFLE_ICU4J", "regex:TREGEX", - "BOUNCYCASTLE-PROVIDER", - "BOUNCYCASTLE-PKIX", - "BOUNCYCASTLE-UTIL", ], "requires": [ "java.logging", @@ -414,6 +411,29 @@ "spotbugsIgnoresGenerated": True, }, + "com.oracle.graal.python.bouncycastle": { + "subDir": "graalpython", + "sourceDirs": ["src"], + "dependencies": [ + "GRAALPYTHON", + "BOUNCYCASTLE-PROVIDER", + "BOUNCYCASTLE-PKIX", + "BOUNCYCASTLE-UTIL", + ], + "requires": [ + "java.logging", + "java.management", + "jdk.management", + "jdk.unsupported", + "jdk.security.auth", + ], + "jacoco": "include", + "checkstyle": "com.oracle.graal.python", + "javaCompliance": "17+", + "workingSets": "Truffle,Python", + "spotbugsIgnoresGenerated": True, + }, + # GRAALPYTHON_UNIT_TESTS "com.oracle.graal.python.test": { "subDir": "graalpython", @@ -862,6 +882,7 @@ "default_vm_args": [ "--vm.Xss16777216", # request 16M of stack '--vm.-enable-native-access=org.graalvm.shadowed.jline', + '--vm.-add-modules=graalpython.bouncycastle,org.bouncycastle.provider,org.bouncycastle.pkix,org.bouncycastle.util', ], "multitarget": [ {"os": ["linux"], "libc": ["glibc", "default"], "compiler": ["llvm-toolchain", "host", "*"]}, @@ -881,6 +902,7 @@ "build_args": [ # From mx.graalpython/native-image.properties "--add-exports", "org.graalvm.nativeimage/org.graalvm.nativeimage.impl=ALL-UNNAMED", + "--add-exports", "org.graalvm.py/com.oracle.graal.python.builtins.objects.ssl=ALL-UNNAMED", "-R:StackSize=16777216", "-H:+AddAllCharsets", "-H:IncludeLocales=no,be,ro,ru,es,se,in,ka,hu,hr,bg,is,mk,da,nn,cs,sq,fr,pl,fo,bs,kl,fa,sv,it,uk,af,tg,ps,de", @@ -1036,11 +1058,47 @@ ], }, + "GRAALPYTHON_BOUNCYCASTLE": { + "dependencies": [ + "com.oracle.graal.python.bouncycastle", + ], + "distDependencies": [ + "GRAALPYTHON", + "truffle:TRUFFLE_API", + "tools:TRUFFLE_PROFILER", + "regex:TREGEX", + "sdk:POLYGLOT", + "sdk:NATIVEIMAGE", + "sdk:COLLECTIONS", + "truffle:TRUFFLE_NFI", + "truffle:TRUFFLE_NFI_LIBFFI", + "truffle:TRUFFLE_NFI_PANAMA", + "truffle:TRUFFLE_ICU4J", + "truffle:TRUFFLE_XZ", + ], + "exclude": [ + "BOUNCYCASTLE-PROVIDER", + "BOUNCYCASTLE-PKIX", + "BOUNCYCASTLE-UTIL", + ], + "description": "Optional GraalPy BouncyCastle integration.", + "maven": { + "artifactId": "python-bouncycastle-support", + "groupId": "org.graalvm.python", + "tag": ["public"], + }, + }, + "GRAALPYTHON": { "moduleInfo": { "name": "org.graalvm.py", "exports": [ "com.oracle.graal.python.* to org.graalvm.py.enterprise", + "com.oracle.graal.python.builtins.objects.ssl to graalpython.bouncycastle", + "com.oracle.graal.python.runtime.crypto", + ], + "uses": [ + "com.oracle.graal.python.runtime.crypto.BouncyCastleSupport", ], }, "useModulePath": True, @@ -1070,11 +1128,6 @@ "jdk.unsupported", "jdk.security.auth", ], - "exclude": [ - "BOUNCYCASTLE-PROVIDER", - "BOUNCYCASTLE-PKIX", - "BOUNCYCASTLE-UTIL", - ], "description": "GraalPy, a high-performance embeddable Python 3 runtime. This artifact includes the core language runtime without standard libraries. It is not recommended to depend on the artifact directly. Instead, use \'org.graalvm.polyglot:python\' or \'org.graalvm.polyglot:python-community\' to ensure all dependencies are pulled in correctly.", "maven": { "artifactId": "python-language", @@ -1428,6 +1481,7 @@ "distDependencies": [ "graalpython:GRAALPYTHON-LAUNCHER", "graalpython:GRAALPYTHON", + "graalpython:GRAALPYTHON_BOUNCYCASTLE", "graalpython:BOUNCYCASTLE-PROVIDER", "graalpython:BOUNCYCASTLE-PKIX", "graalpython:BOUNCYCASTLE-UTIL",