diff --git a/MODULE.bazel b/MODULE.bazel index 9ff37b4d6..724b678fe 100644 --- a/MODULE.bazel +++ b/MODULE.bazel @@ -78,6 +78,8 @@ maven.install( "org.slf4j:log4j-over-slf4j:2.0.12", "org.slf4j:slf4j-simple:2.0.12", "software.amazon.awssdk:s3:2.26.12", + "org.bouncycastle:bcprov-jdk15on:1.68", + "org.bouncycastle:bcpg-jdk15on:1.68", ], fail_if_repin_required = True, fetch_sources = True, diff --git a/private/rules/maven_publish.bzl b/private/rules/maven_publish.bzl index 5e7d07779..bb6879518 100644 --- a/private/rules/maven_publish.bzl +++ b/private/rules/maven_publish.bzl @@ -14,6 +14,9 @@ export MAVEN_REPO="${{MAVEN_REPO:-{maven_repo}}}" export GPG_SIGN="${{GPG_SIGN:-{gpg_sign}}}" export MAVEN_USER="${{MAVEN_USER:-{user}}}" export MAVEN_PASSWORD="${{MAVEN_PASSWORD:-{password}}}" +export USE_IN_MEMORY_PGP_KEYS="${{USE_IN_MEMORY_PGP_KEYS:-{use_in_memory_pgp_keys}}}" +export PGP_SIGNING_KEY="${{PGP_SIGNING_KEY:-{pgp_signing_key}}}" +export PGP_SIGNING_PWD="${{PGP_SIGNING_PWD:-{pgp_signing_pwd}}}" echo Uploading "{coordinates}" to "${{MAVEN_REPO}}" {uploader} "{coordinates}" '{pom}' '{artifact}' '{classifier_artifacts}' $@ """ @@ -29,6 +32,9 @@ def _maven_publish_impl(ctx): gpg_sign = ctx.var.get("gpg_sign", "false") user = ctx.var.get("maven_user", "") password = ctx.var.get("maven_password", "") + use_in_memory_pgp_keys = ctx.var.get("use_in_memory_pgp_keys", "'false'") + pgp_signing_key = ctx.var.get("pgp_signing_key", "''") + pgp_signing_pwd = ctx.var.get("pgp_signing_pwd", "''") if password: print("WARNING: using --define to set maven_password is insecure. Set env var MAVEN_PASSWORD=xxx instead.") @@ -55,6 +61,9 @@ def _maven_publish_impl(ctx): gpg_sign = _escape_arg(gpg_sign), maven_repo = _escape_arg(maven_repo), password = _escape_arg(password), + use_in_memory_pgp_keys = _escape_arg(use_in_memory_pgp_keys), + pgp_signing_key = _escape_arg(pgp_signing_key), + pgp_signing_pwd = _escape_arg(pgp_signing_pwd), user = _escape_arg(user), pom = ctx.file.pom.short_path, artifact = artifacts_short_path, @@ -97,6 +106,9 @@ using `--define` or via environment variables (in all caps, e.g. `MAVEN_REPO`): maven_repo: A URL for the repo to use. May be "https" or "file". maven_user: The user name to use when uploading to the maven repository. maven_password: The password to use when uploading to the maven repository. + use_in_memory_pgp_keys: Whether to sign artifacts using in memory PGP secrets + pgp_signing_key = The secret key to sign the artifact with + pgp_signing_pwd = Password for the secret key When signing with GPG, the current default key is used. """, diff --git a/private/tools/java/com/github/bazelbuild/rules_jvm_external/maven/BUILD b/private/tools/java/com/github/bazelbuild/rules_jvm_external/maven/BUILD index 8301ae903..61fae5b17 100644 --- a/private/tools/java/com/github/bazelbuild/rules_jvm_external/maven/BUILD +++ b/private/tools/java/com/github/bazelbuild/rules_jvm_external/maven/BUILD @@ -2,7 +2,7 @@ load("@rules_jvm_external//:defs.bzl", "artifact") java_binary( name = "MavenPublisher", - srcs = ["MavenPublisher.java"], + srcs = ["MavenPublisher.java", "MavenSigning.java"], main_class = "com.github.bazelbuild.rules_jvm_external.maven.MavenPublisher", visibility = ["//visibility:public"], deps = [ @@ -31,6 +31,14 @@ java_binary( "software.amazon.awssdk:s3", repository_name = "rules_jvm_external_deps", ), + artifact( + "org.bouncycastle:bcprov-jdk15on", + repository_name = "rules_jvm_external_deps", + ), + artifact( + "org.bouncycastle:bcpg-jdk15on", + repository_name = "rules_jvm_external_deps", + ), ], ) diff --git a/private/tools/java/com/github/bazelbuild/rules_jvm_external/maven/MavenPublisher.java b/private/tools/java/com/github/bazelbuild/rules_jvm_external/maven/MavenPublisher.java index a9af8b5fe..112d05328 100644 --- a/private/tools/java/com/github/bazelbuild/rules_jvm_external/maven/MavenPublisher.java +++ b/private/tools/java/com/github/bazelbuild/rules_jvm_external/maven/MavenPublisher.java @@ -17,6 +17,8 @@ package com.github.bazelbuild.rules_jvm_external.maven; +import static com.github.bazelbuild.rules_jvm_external.maven.MavenSigning.in_memory_pgp_sign; +import static com.github.bazelbuild.rules_jvm_external.maven.MavenSigning.gpg_sign; import static java.nio.charset.StandardCharsets.US_ASCII; import static java.nio.charset.StandardCharsets.UTF_8; import static java.util.concurrent.TimeUnit.MINUTES; @@ -78,6 +80,11 @@ public static void main(String[] args) boolean gpgSign = Boolean.parseBoolean(System.getenv("GPG_SIGN")); Credentials credentials = new BasicAuthCredentials(System.getenv("MAVEN_USER"), System.getenv("MAVEN_PASSWORD")); + boolean useInMemoryPgpKeys = Boolean.parseBoolean(System.getenv("USE_IN_MEMORY_PGP_KEYS")); + String signingKey = System.getenv("PGP_SIGNING_KEY"); + String signingPassword = System.getenv("PGP_SIGNING_PWD"); + MavenSigning.SigningMetadata signingMetadata = + new MavenSigning.SigningMetadata(gpgSign, useInMemoryPgpKeys, signingKey, signingPassword); List parts = Arrays.asList(args[0].split(":")); if (parts.size() != 3) { @@ -93,12 +100,12 @@ public static void main(String[] args) try { List> futures = new ArrayList<>(); - futures.add(upload(repo, credentials, coords, ".pom", pom, gpgSign)); + futures.add(upload(repo, credentials, coords, ".pom", pom, signingMetadata)); if (mainArtifact != null) { String ext = com.google.common.io.Files.getFileExtension(mainArtifact.getFileName().toString()); - futures.add(upload(repo, credentials, coords, "." + ext, mainArtifact, gpgSign)); + futures.add(upload(repo, credentials, coords, "." + ext, mainArtifact, signingMetadata)); } if (args.length > 3 && !args[3].isEmpty()) { @@ -115,7 +122,7 @@ public static void main(String[] args) coords, String.format("-%s.%s", classifier, ext), artifact, - gpgSign)); + signingMetadata)); } } @@ -149,7 +156,7 @@ private static CompletableFuture upload( Coordinates coords, String append, Path item, - boolean gpgSign) + MavenSigning.SigningMetadata signingMetadata) throws IOException, InterruptedException { String base = @@ -174,10 +181,27 @@ private static CompletableFuture upload( uploads.add(upload(String.format("%s%s.md5", base, append), credentials, md5)); uploads.add(upload(String.format("%s%s.sha1", base, append), credentials, sha1)); - if (gpgSign) { - uploads.add(upload(String.format("%s%s.asc", base, append), credentials, sign(item))); - uploads.add(upload(String.format("%s%s.md5.asc", base, append), credentials, sign(md5))); - uploads.add(upload(String.format("%s%s.sha1.asc", base, append), credentials, sign(sha1))); + MavenSigning.SigningMethod signingMethod = signingMetadata.signingMethod; + if (signingMethod.equals(MavenSigning.SigningMethod.GPG)) { + uploads.add(upload(String.format("%s%s.asc", base, append), credentials, gpg_sign(item))); + uploads.add(upload(String.format("%s%s.md5.asc", base, append), credentials, gpg_sign(md5))); + uploads.add(upload(String.format("%s%s.sha1.asc", base, append), credentials, gpg_sign(sha1))); + } else if (signingMethod.equals(MavenSigning.SigningMethod.PGP)) { + uploads.add(upload( + String.format("%s%s.asc", base, append), + credentials, + in_memory_pgp_sign(item, signingMetadata.signingKey, signingMetadata.signingPassword) + )); + uploads.add(upload( + String.format("%s%s.md5.asc", base, append), + credentials, + in_memory_pgp_sign(md5, signingMetadata.signingKey, signingMetadata.signingPassword) + )); + uploads.add(upload( + String.format("%s%s.sha1.asc", base, append), + credentials, + in_memory_pgp_sign(sha1, signingMetadata.signingKey, signingMetadata.signingPassword) + )); } return CompletableFuture.allOf(uploads.toArray(new CompletableFuture[0])); @@ -335,51 +359,6 @@ private static Callable arUpload(String targetUrl, Path toUpload) { }; } - private static Path sign(Path toSign) throws IOException, InterruptedException { - LOG.info("Signing " + toSign); - - // Ideally, we'd use BouncyCastle for this, but for now brute force by assuming - // the gpg binary is on the path - - Path dir = Files.createTempDirectory("maven-sign"); - Path file = dir.resolve(toSign.getFileName() + ".asc"); - - Process gpg = - new ProcessBuilder( - "gpg", - "--use-agent", - "--armor", - "--detach-sign", - "--no-tty", - "-o", - file.toAbsolutePath().toString(), - toSign.toAbsolutePath().toString()) - .inheritIO() - .start(); - gpg.waitFor(); - if (gpg.exitValue() != 0) { - throw new IllegalStateException("Unable to sign: " + toSign); - } - - // Verify the signature - Process verify = - new ProcessBuilder( - "gpg", - "--verify", - "--verbose", - "--verbose", - file.toAbsolutePath().toString(), - toSign.toAbsolutePath().toString()) - .inheritIO() - .start(); - verify.waitFor(); - if (verify.exitValue() != 0) { - throw new IllegalStateException("Unable to verify signature of " + toSign); - } - - return file; - } - private static class Coordinates { private final String groupId; private final String artifactId; diff --git a/private/tools/java/com/github/bazelbuild/rules_jvm_external/maven/MavenSigning.java b/private/tools/java/com/github/bazelbuild/rules_jvm_external/maven/MavenSigning.java new file mode 100644 index 000000000..11e9e7ec8 --- /dev/null +++ b/private/tools/java/com/github/bazelbuild/rules_jvm_external/maven/MavenSigning.java @@ -0,0 +1,245 @@ +package com.github.bazelbuild.rules_jvm_external.maven; + +import org.bouncycastle.bcpg.ArmoredOutputStream; +import org.bouncycastle.bcpg.BCPGOutputStream; +import org.bouncycastle.openpgp.PGPCompressedData; +import org.bouncycastle.openpgp.PGPException; +import org.bouncycastle.openpgp.PGPObjectFactory; +import org.bouncycastle.openpgp.PGPPrivateKey; +import org.bouncycastle.openpgp.PGPPublicKey; +import org.bouncycastle.openpgp.PGPSecretKey; +import org.bouncycastle.openpgp.PGPSignature; +import org.bouncycastle.openpgp.PGPSignatureGenerator; +import org.bouncycastle.openpgp.PGPSignatureList; +import org.bouncycastle.openpgp.PGPUtil; +import org.bouncycastle.openpgp.jcajce.JcaPGPSecretKeyRing; +import org.bouncycastle.openpgp.operator.PBESecretKeyDecryptor; +import org.bouncycastle.openpgp.operator.bc.BcKeyFingerprintCalculator; +import org.bouncycastle.openpgp.operator.bc.BcPBESecretKeyDecryptorBuilder; +import org.bouncycastle.openpgp.operator.bc.BcPGPContentSignerBuilder; +import org.bouncycastle.openpgp.operator.bc.BcPGPContentVerifierBuilderProvider; +import org.bouncycastle.openpgp.operator.bc.BcPGPDigestCalculatorProvider; + +import java.io.BufferedInputStream; +import java.io.ByteArrayInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.UncheckedIOException; +import java.math.BigInteger; +import java.nio.file.Files; +import java.nio.file.Path; +import java.util.Base64; +import java.util.logging.Logger; + +public class MavenSigning { + private static final int BUFFER = 4096; + private static final Logger LOG = Logger.getLogger(MavenSigning.class.getName()); + + /** + * This method is based on the following Gradle code: + * ... + * ... + * ... + * ... + * + * @param toSign + * @param key + * @param password + * @return + * @throws IOException + */ + protected static Path in_memory_pgp_sign(Path toSign, String key, String password) throws IOException { + LOG.info("Signing " + toSign + " with in-memory PGP keys"); + + Path dir = Files.createTempDirectory("maven-sign"); + Path signatureOutputPath = dir.resolve(toSign.getFileName() + ".asc"); + + PGPSecretKey pgpSecretKey; + // CI builder should have the key in the environment variable in Base64 format + try (InputStream in = PGPUtil.getDecoderStream(new ByteArrayInputStream(Base64.getDecoder().decode(key)))) { + pgpSecretKey = new JcaPGPSecretKeyRing(in).getSecretKey(); + } catch (Exception e) { + throw new IOException("Could not read PGP secret key", e); + } + + // Decrypt the PGPSecretKey to get a PGPPrivateKey + PGPPrivateKey privateKey = createPrivateKey(pgpSecretKey, password); + + try { + // Create a PGPSignatureGenerator with the PGPPrivateKey + PGPSignatureGenerator signatureGenerator = new PGPSignatureGenerator( + new BcPGPContentSignerBuilder(pgpSecretKey.getPublicKey().getAlgorithm(), PGPUtil.SHA512) + ); + signatureGenerator.init(PGPSignature.BINARY_DOCUMENT, privateKey); + + // Read the input file and write its contents to the PGPSignatureGenerator + try (InputStream in = new BufferedInputStream(Files.newInputStream(toSign))) { + int ch; + while ((ch = in.read()) >= 0) { + signatureGenerator.update((byte) ch); + } + } + + // Generate the signature + PGPSignature signature = signatureGenerator.generate(); + + // Write the signature to the output file + try (ArmoredOutputStream out = + new ArmoredOutputStream(new BCPGOutputStream(Files.newOutputStream(signatureOutputPath))) + ) { + signature.encode(out, true /* forTransfer */); + out.flush(); + } + } catch (PGPException e) { + throw new RuntimeException(e); + } + + // Verify the signature + PGPSignatureList pgpSignatures = readSignatures(signatureOutputPath); + if (pgpSignatures == null) { + throw new IOException("Could not read PGP signatures"); + } + + for (PGPSignature signature : pgpSignatures) { + try { + if (!verify(toSign, signature, pgpSecretKey.getPublicKey())) { + throw new RuntimeException( + String.format("Could not verify PGP signature for file %s!", toSign.getFileName()) + ); + } else { + LOG.info(String.format("PGP signature verified for file %s", toSign.getFileName())); + } + } catch (PGPException e) { + throw new RuntimeException(e); + } + } + + return signatureOutputPath; + } + + private static String bytesToHex(byte[] bytes) { + return String.format("%0" + (bytes.length << 1) + "x", new BigInteger(1, bytes)); + } + + private static boolean verify(Path originFilePath, PGPSignature signature, PGPPublicKey publicKey) throws PGPException { + signature.init(new BcPGPContentVerifierBuilderProvider(), publicKey); + + LOG.info(String.format("[Verify] Public Key Fingerprint: %s", bytesToHex(publicKey.getFingerprint()))); + + byte[] buffer = new byte[BUFFER]; + int len; + try (InputStream in = new BufferedInputStream(Files.newInputStream(originFilePath))) { + while ((len = in.read(buffer)) >= 0) { + signature.update(buffer, 0, len); + } + } catch (IOException e) { + throw new UncheckedIOException(e); + } + return signature.verify(); + } + + private static PGPSignatureList readSignatures(Path signaturePath) { + try ( + InputStream stream = new BufferedInputStream(Files.newInputStream(signaturePath)); + InputStream decoderStream = PGPUtil.getDecoderStream(stream) + ) { + return readSignatureList(decoderStream); + } catch (IOException | PGPException e) { + throw new RuntimeException(e); + } + } + + private static PGPSignatureList readSignatureList(InputStream decoderStream) throws IOException, PGPException { + PGPObjectFactory objectFactory = new PGPObjectFactory(decoderStream, new BcKeyFingerprintCalculator()); + Object nextObject = objectFactory.nextObject(); + if (nextObject instanceof PGPSignatureList) { + return (PGPSignatureList) nextObject; + } else if (nextObject instanceof PGPCompressedData) { + return readSignatureList(((PGPCompressedData) nextObject).getDataStream()); + } else { + LOG.warning(String.format("Skip parsing signature list in %s.", nextObject == null ? "invalid file" : nextObject.getClass())); + return null; + } + } + + private static PGPPrivateKey createPrivateKey(PGPSecretKey secretKey, String password) { + try { + PBESecretKeyDecryptor decryptor = new BcPBESecretKeyDecryptorBuilder(new BcPGPDigestCalculatorProvider()).build(password.toCharArray()); + return secretKey.extractPrivateKey(decryptor); + } catch (PGPException e) { + throw new RuntimeException("Could not extract private key", e); + } + } + + protected static Path gpg_sign(Path toSign) throws IOException, InterruptedException { + LOG.info("Signing " + toSign + " with GPG"); + + // Ideally, we'd use BouncyCastle for this, but for now brute force by assuming + // the gpg binary is on the path + + Path dir = Files.createTempDirectory("maven-sign"); + Path file = dir.resolve(toSign.getFileName() + ".asc"); + + Process gpg = + new ProcessBuilder( + "gpg", + "--use-agent", + "--armor", + "--detach-sign", + "--no-tty", + "-o", + file.toAbsolutePath().toString(), + toSign.toAbsolutePath().toString()) + .inheritIO() + .start(); + gpg.waitFor(); + if (gpg.exitValue() != 0) { + throw new IllegalStateException("Unable to sign: " + toSign); + } + + // Verify the signature + Process verify = + new ProcessBuilder( + "gpg", + "--verify", + "--verbose", + "--verbose", + file.toAbsolutePath().toString(), + toSign.toAbsolutePath().toString()) + .inheritIO() + .start(); + verify.waitFor(); + if (verify.exitValue() != 0) { + throw new IllegalStateException("Unable to verify signature of " + toSign); + } + + return file; + } + + protected enum SigningMethod { + GPG, + PGP, + NONE + } + + protected static class SigningMetadata { + protected final String signingKey; + protected final String signingPassword; + protected final SigningMethod signingMethod; + + protected SigningMetadata(boolean gpgSign, boolean useInMemoryPgpKeys, String signingKey, String signingPassword) { + this.signingKey = signingKey; + this.signingPassword = signingPassword; + if (gpgSign && useInMemoryPgpKeys) { + throw new IllegalArgumentException("Cannot use in-memory PGP keys with GPG signing"); + } + if (gpgSign) { + this.signingMethod = SigningMethod.GPG; + } else if (useInMemoryPgpKeys) { + this.signingMethod = SigningMethod.PGP; + } else { + this.signingMethod = SigningMethod.NONE; + } + } + } +} diff --git a/repositories.bzl b/repositories.bzl index 2faeaf835..849ab165f 100644 --- a/repositories.bzl +++ b/repositories.bzl @@ -89,6 +89,8 @@ def rules_jvm_external_deps( "org.slf4j:log4j-over-slf4j:2.0.12", "org.slf4j:slf4j-simple:2.0.12", "software.amazon.awssdk:s3:2.26.12", + "org.bouncycastle:bcprov-jdk15on:1.68", + "org.bouncycastle:bcpg-jdk15on:1.68", ], maven_install_json = deps_lock_file, fail_if_repin_required = True, diff --git a/rules_jvm_external_deps_install.json b/rules_jvm_external_deps_install.json index 57164b097..c5aaaf9e5 100644 --- a/rules_jvm_external_deps_install.json +++ b/rules_jvm_external_deps_install.json @@ -1,7 +1,7 @@ { "__AUTOGENERATED_FILE_DO_NOT_MODIFY_THIS_FILE_MANUALLY": "THERE_IS_NO_DATA_ONLY_ZUUL", - "__INPUT_ARTIFACTS_HASH": -1390499893, - "__RESOLVED_ARTIFACTS_HASH": 1502448316, + "__INPUT_ARTIFACTS_HASH": -951616327, + "__RESOLVED_ARTIFACTS_HASH": -84218881, "artifacts": { "aopalliance:aopalliance": { "shasums": { @@ -661,6 +661,20 @@ }, "version": "3.9.8" }, + "org.bouncycastle:bcpg-jdk15on": { + "shasums": { + "jar": "2251d9c9faa0ee534ab159a6dac1193a69b8a831f0a0e593dc79e34e7e256a4f", + "sources": "1689a9e2c6629c2b48015def02e7ad531d2fd485bdafbd177502aeeb232f321c" + }, + "version": "1.68" + }, + "org.bouncycastle:bcprov-jdk15on": { + "shasums": { + "jar": "f732a46c8de7e2232f2007c682a21d1f4cc8a8a0149b6b7bd6aa1afdc65a0f8d", + "sources": "d9bb57dd73ae7ae3a3b37fcbee6e91ca87156343123d6d3079712928088fb370" + }, + "version": "1.68" + }, "org.checkerframework:checker-qual": { "shasums": { "jar": "30ed439602b6c2d4aaea2a85e58e388556f0cc7ae68ed29649bc1cd0c0102cd9", @@ -1339,6 +1353,9 @@ "org.codehaus.plexus:plexus-sec-dispatcher", "org.codehaus.plexus:plexus-utils" ], + "org.bouncycastle:bcpg-jdk15on": [ + "org.bouncycastle:bcprov-jdk15on" + ], "org.codehaus.plexus:plexus-cipher": [ "javax.inject:javax.inject" ], @@ -2417,6 +2434,184 @@ "org.apache.maven.settings.merge", "org.apache.maven.settings.validation" ], + "org.bouncycastle:bcpg-jdk15on": [ + "org.bouncycastle.apache.bzip2", + "org.bouncycastle.bcpg", + "org.bouncycastle.bcpg.attr", + "org.bouncycastle.bcpg.sig", + "org.bouncycastle.gpg", + "org.bouncycastle.gpg.keybox", + "org.bouncycastle.gpg.keybox.bc", + "org.bouncycastle.gpg.keybox.jcajce", + "org.bouncycastle.openpgp", + "org.bouncycastle.openpgp.bc", + "org.bouncycastle.openpgp.examples", + "org.bouncycastle.openpgp.jcajce", + "org.bouncycastle.openpgp.operator", + "org.bouncycastle.openpgp.operator.bc", + "org.bouncycastle.openpgp.operator.jcajce" + ], + "org.bouncycastle:bcprov-jdk15on": [ + "org.bouncycastle", + "org.bouncycastle.asn1", + "org.bouncycastle.asn1.anssi", + "org.bouncycastle.asn1.bc", + "org.bouncycastle.asn1.bsi", + "org.bouncycastle.asn1.cmc", + "org.bouncycastle.asn1.cmp", + "org.bouncycastle.asn1.cms", + "org.bouncycastle.asn1.cms.ecc", + "org.bouncycastle.asn1.crmf", + "org.bouncycastle.asn1.cryptlib", + "org.bouncycastle.asn1.cryptopro", + "org.bouncycastle.asn1.dvcs", + "org.bouncycastle.asn1.eac", + "org.bouncycastle.asn1.edec", + "org.bouncycastle.asn1.esf", + "org.bouncycastle.asn1.ess", + "org.bouncycastle.asn1.est", + "org.bouncycastle.asn1.gm", + "org.bouncycastle.asn1.gnu", + "org.bouncycastle.asn1.iana", + "org.bouncycastle.asn1.icao", + "org.bouncycastle.asn1.isara", + "org.bouncycastle.asn1.isismtt", + "org.bouncycastle.asn1.isismtt.ocsp", + "org.bouncycastle.asn1.isismtt.x509", + "org.bouncycastle.asn1.iso", + "org.bouncycastle.asn1.kisa", + "org.bouncycastle.asn1.microsoft", + "org.bouncycastle.asn1.misc", + "org.bouncycastle.asn1.mozilla", + "org.bouncycastle.asn1.nist", + "org.bouncycastle.asn1.nsri", + "org.bouncycastle.asn1.ntt", + "org.bouncycastle.asn1.ocsp", + "org.bouncycastle.asn1.oiw", + "org.bouncycastle.asn1.pkcs", + "org.bouncycastle.asn1.rosstandart", + "org.bouncycastle.asn1.sec", + "org.bouncycastle.asn1.smime", + "org.bouncycastle.asn1.teletrust", + "org.bouncycastle.asn1.tsp", + "org.bouncycastle.asn1.ua", + "org.bouncycastle.asn1.util", + "org.bouncycastle.asn1.x500", + "org.bouncycastle.asn1.x500.style", + "org.bouncycastle.asn1.x509", + "org.bouncycastle.asn1.x509.qualified", + "org.bouncycastle.asn1.x509.sigi", + "org.bouncycastle.asn1.x9", + "org.bouncycastle.crypto", + "org.bouncycastle.crypto.agreement", + "org.bouncycastle.crypto.agreement.jpake", + "org.bouncycastle.crypto.agreement.kdf", + "org.bouncycastle.crypto.agreement.srp", + "org.bouncycastle.crypto.commitments", + "org.bouncycastle.crypto.digests", + "org.bouncycastle.crypto.ec", + "org.bouncycastle.crypto.encodings", + "org.bouncycastle.crypto.engines", + "org.bouncycastle.crypto.examples", + "org.bouncycastle.crypto.generators", + "org.bouncycastle.crypto.io", + "org.bouncycastle.crypto.kems", + "org.bouncycastle.crypto.macs", + "org.bouncycastle.crypto.modes", + "org.bouncycastle.crypto.modes.gcm", + "org.bouncycastle.crypto.modes.kgcm", + "org.bouncycastle.crypto.paddings", + "org.bouncycastle.crypto.params", + "org.bouncycastle.crypto.parsers", + "org.bouncycastle.crypto.prng", + "org.bouncycastle.crypto.prng.drbg", + "org.bouncycastle.crypto.signers", + "org.bouncycastle.crypto.util", + "org.bouncycastle.i18n", + "org.bouncycastle.i18n.filter", + "org.bouncycastle.iana", + "org.bouncycastle.its.asn1", + "org.bouncycastle.jcajce", + "org.bouncycastle.jcajce.interfaces", + "org.bouncycastle.jcajce.io", + "org.bouncycastle.jcajce.provider.asymmetric", + "org.bouncycastle.jcajce.provider.asymmetric.dh", + "org.bouncycastle.jcajce.provider.asymmetric.dsa", + "org.bouncycastle.jcajce.provider.asymmetric.dstu", + "org.bouncycastle.jcajce.provider.asymmetric.ec", + "org.bouncycastle.jcajce.provider.asymmetric.ecgost", + "org.bouncycastle.jcajce.provider.asymmetric.ecgost12", + "org.bouncycastle.jcajce.provider.asymmetric.edec", + "org.bouncycastle.jcajce.provider.asymmetric.elgamal", + "org.bouncycastle.jcajce.provider.asymmetric.gost", + "org.bouncycastle.jcajce.provider.asymmetric.ies", + "org.bouncycastle.jcajce.provider.asymmetric.rsa", + "org.bouncycastle.jcajce.provider.asymmetric.util", + "org.bouncycastle.jcajce.provider.asymmetric.x509", + "org.bouncycastle.jcajce.provider.config", + "org.bouncycastle.jcajce.provider.digest", + "org.bouncycastle.jcajce.provider.drbg", + "org.bouncycastle.jcajce.provider.keystore", + "org.bouncycastle.jcajce.provider.keystore.bc", + "org.bouncycastle.jcajce.provider.keystore.bcfks", + "org.bouncycastle.jcajce.provider.keystore.pkcs12", + "org.bouncycastle.jcajce.provider.symmetric", + "org.bouncycastle.jcajce.provider.symmetric.util", + "org.bouncycastle.jcajce.provider.util", + "org.bouncycastle.jcajce.spec", + "org.bouncycastle.jcajce.util", + "org.bouncycastle.jce", + "org.bouncycastle.jce.exception", + "org.bouncycastle.jce.interfaces", + "org.bouncycastle.jce.netscape", + "org.bouncycastle.jce.provider", + "org.bouncycastle.jce.spec", + "org.bouncycastle.math", + "org.bouncycastle.math.ec", + "org.bouncycastle.math.ec.custom.djb", + "org.bouncycastle.math.ec.custom.gm", + "org.bouncycastle.math.ec.custom.sec", + "org.bouncycastle.math.ec.endo", + "org.bouncycastle.math.ec.rfc7748", + "org.bouncycastle.math.ec.rfc8032", + "org.bouncycastle.math.ec.tools", + "org.bouncycastle.math.field", + "org.bouncycastle.math.raw", + "org.bouncycastle.pqc.asn1", + "org.bouncycastle.pqc.crypto", + "org.bouncycastle.pqc.crypto.gmss", + "org.bouncycastle.pqc.crypto.gmss.util", + "org.bouncycastle.pqc.crypto.lms", + "org.bouncycastle.pqc.crypto.mceliece", + "org.bouncycastle.pqc.crypto.newhope", + "org.bouncycastle.pqc.crypto.qtesla", + "org.bouncycastle.pqc.crypto.rainbow", + "org.bouncycastle.pqc.crypto.rainbow.util", + "org.bouncycastle.pqc.crypto.sphincs", + "org.bouncycastle.pqc.crypto.util", + "org.bouncycastle.pqc.crypto.xmss", + "org.bouncycastle.pqc.jcajce.interfaces", + "org.bouncycastle.pqc.jcajce.provider", + "org.bouncycastle.pqc.jcajce.provider.gmss", + "org.bouncycastle.pqc.jcajce.provider.lms", + "org.bouncycastle.pqc.jcajce.provider.mceliece", + "org.bouncycastle.pqc.jcajce.provider.newhope", + "org.bouncycastle.pqc.jcajce.provider.qtesla", + "org.bouncycastle.pqc.jcajce.provider.rainbow", + "org.bouncycastle.pqc.jcajce.provider.sphincs", + "org.bouncycastle.pqc.jcajce.provider.util", + "org.bouncycastle.pqc.jcajce.provider.xmss", + "org.bouncycastle.pqc.jcajce.spec", + "org.bouncycastle.pqc.math.linearalgebra", + "org.bouncycastle.util", + "org.bouncycastle.util.encoders", + "org.bouncycastle.util.io", + "org.bouncycastle.util.io.pem", + "org.bouncycastle.util.test", + "org.bouncycastle.x509", + "org.bouncycastle.x509.extension", + "org.bouncycastle.x509.util" + ], "org.checkerframework:checker-qual": [ "org.checkerframework.checker.builder.qual", "org.checkerframework.checker.calledmethods.qual", @@ -3038,6 +3233,10 @@ "org.apache.maven:maven-settings-builder", "org.apache.maven:maven-settings-builder:jar:sources", "org.apache.maven:maven-settings:jar:sources", + "org.bouncycastle:bcpg-jdk15on", + "org.bouncycastle:bcpg-jdk15on:jar:sources", + "org.bouncycastle:bcprov-jdk15on", + "org.bouncycastle:bcprov-jdk15on:jar:sources", "org.checkerframework:checker-qual", "org.checkerframework:checker-qual:jar:sources", "org.codehaus.mojo:animal-sniffer-annotations", @@ -3302,6 +3501,12 @@ "io.netty.util.internal.Hidden$NettyBlockHoundIntegration" ] }, + "org.bouncycastle:bcprov-jdk15on": { + "java.security.Provider": [ + "org.bouncycastle.jce.provider.BouncyCastleProvider", + "org.bouncycastle.pqc.jcajce.provider.BouncyCastlePQCProvider" + ] + }, "org.slf4j:jcl-over-slf4j": { "org.apache.commons.logging.LogFactory": [ "org.apache.commons.logging.impl.SLF4JLogFactory"