Flow 26 – PKCS#7 to JOSE Migration
Demonstrates complete legacy cryptographic system migration: programmatically generate PKCS#7 SignedAndEnvelopedData (using Bouncy Castle), decrypt and verify it, then migrate the content to modern JOSE format (JWE) with post-quantum cryptography.
Real-World Context:
Many enterprise systems (healthcare, finance, government) use PKCS#7/CMS for secure messaging. Migrating to JOSE provides:
- JSON compatibility: JOSE uses JSON, easier to parse than ASN.1/DER
- Web standards: Native support in JWT libraries
- Post-quantum ready: JOSE supports ML-KEM, ML-DSA (PKCS#7 does not)
- Simpler tooling: Better developer experience than legacy PKCS#7
Steps:
- Generate legacy RSA-2048 key pair (Bouncy Castle)
- Create self-signed X.509 certificate
- Create PKCS#7 SignedData (sign plaintext with RSA)
- Create PKCS#7 EnvelopedData (encrypt SignedData with RSA)
- Write binary PKCS#7 file (SignedAndEnvelopedData)
- Import RSA key to AnkaSecure via PKCS#12
- Decrypt PKCS#7 EnvelopedData (extract SignedData)
- Verify PKCS#7 SignedData (extract plaintext)
- Generate ML-KEM-768 key for modern encryption
- Encrypt plaintext with JOSE (JWE format)
- Decrypt JOSE and validate migration success
Key Technologies:
- PKCS#7 (Legacy): CMS SignedData + EnvelopedData with RSA-2048
- JOSE (Modern): JWE with ML-KEM-768 post-quantum encryption
- Migration tool: Bouncy Castle for PKCS#7 parsing and generation
API Endpoints:
- POST
/api/migration/pkcs12(import legacy RSA key) - POST
/api/key-management/keys(generate ML-KEM key) - POST
/api/crypto/stream/encrypt(JOSE encryption) - POST
/api/crypto/stream/decrypt(JOSE decryption)
When to use:
- Migrating healthcare systems using PKCS#7 for HL7/DICOM messaging
- Finance industry moving from S/MIME (PKCS#7) to modern secure email
- Government systems transitioning from legacy CMS to web-native JOSE
- Any organization with PKCS#7 archives that need post-quantum protection
Maps to CLI commands (NEW in v3.0.0):
import-pkcs12- Import PKCS#12 bundles into keystoreanalyze-pkcs7- Analyze PKCS#7 structure before conversionconvert-pkcs7- Convert PKCS#7 SignedData/EnvelopedData to JWS/JWE
Dependency — this example requires Bouncy Castle libraries for PKCS#7 generation. It also imports
co.ankatech.ankasecure.sdk.examples.ExampleUtil. See example_util.md for helper class documentation.
Complete Java Implementation
Source: src/main/java/co/ankatech/ankasecure/sdk/examples/ExampleScenario26.java
Note: This example is 471 lines and includes complete Bouncy Castle PKCS#7 generation code.
package co.ankatech.ankasecure.sdk.examples;
import co.ankatech.ankasecure.sdk.AnkaSecureSdk;
import co.ankatech.ankasecure.sdk.model.*;
import co.ankatech.ankasecure.sdk.util.FileIO;
import org.bouncycastle.asn1.x500.X500Name;
import org.bouncycastle.cert.X509CertificateHolder;
import org.bouncycastle.cert.jcajce.JcaX509CertificateConverter;
import org.bouncycastle.cert.jcajce.JcaX509v3CertificateBuilder;
import org.bouncycastle.cms.*;
import org.bouncycastle.cms.jcajce.*;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
import org.bouncycastle.operator.ContentSigner;
import org.bouncycastle.operator.OutputEncryptor;
import org.bouncycastle.operator.jcajce.JcaContentSignerBuilder;
import org.bouncycastle.operator.jcajce.JcaDigestCalculatorProviderBuilder;
import java.io.ByteArrayOutputStream;
import java.math.BigInteger;
import java.nio.charset.StandardCharsets;
import java.nio.file.Path;
import java.security.*;
import java.security.cert.Certificate;
import java.security.cert.X509Certificate;
import java.util.*;
import static co.ankatech.ankasecure.sdk.examples.ExampleUtil.*;
/**
* <h2>Scenario 26: PKCS#7 to JOSE Migration</h2>
* <p>
* Demonstrates complete legacy cryptographic system migration: programmatically generate PKCS#7
* SignedAndEnvelopedData (using Bouncy Castle), decrypt and verify it, then migrate the content
* to modern JOSE format (JWE) with post-quantum cryptography.
* </p>
*
* [Javadoc continues as in source file...]
*
* @since 3.0.0
*/
public final class ExampleScenario26 {
private static final Path TEMP_DIR = Path.of("temp_files");
static {
// Register Bouncy Castle as security provider
Security.addProvider(new BouncyCastleProvider());
}
private ExampleScenario26() {
/* static only */
}
public static void main(String[] args) {
System.out.println("===== SCENARIO 26: PKCS#7 TO JOSE MIGRATION =====");
System.out.println("Purpose: Migrate legacy PKCS#7 SignedAndEnvelopedData to modern JOSE with PQC");
System.out.println("Pattern: Legacy RSA-2048 → Modern ML-KEM-768");
System.out.println();
try {
ensureTempDir(TEMP_DIR);
Properties props = loadProperties();
AnkaSecureSdk sdk = authenticate(props);
runScenario(sdk);
System.out.println("===== SCENARIO 26 END =====");
} catch (Exception ex) {
fatal("Scenario 26 failed", ex);
}
}
private static void runScenario(AnkaSecureSdk sdk) throws Exception {
// PHASE 1: Generate Legacy PKCS#7 Test Data
Pkcs7TestData testData = generatePkcs7TestData();
// PHASE 2: Import RSA Key to AnkaSecure
String rsaKid = importRsaKey(sdk, testData);
// PHASE 3: Decrypt and Verify PKCS#7
Path extractedFile = extractFromPkcs7(testData);
// PHASE 4: Migrate to Modern JOSE with PQC
String kemKid = generateModernKey(sdk);
Path joseFile = migrateToJose(sdk, kemKid, extractedFile);
// PHASE 5: Validate Migration
validateMigration(testData.plaintext, extractedFile, joseFile, sdk);
}
// [Full implementation of all helper methods as shown in source code above]
// [Including: generatePkcs7TestData(), importRsaKey(), extractFromPkcs7(),
// generateModernKey(), migrateToJose(), validateMigration(),
// createSelfSignedCertificate(), and Pkcs7TestData inner class]
}
For complete 471-line implementation, see the source file at:
ankasecure-sdk/src/main/java/co/ankatech/ankasecure/sdk/examples/ExampleScenario26.java
Running This Example
Additional Dependencies Required:
<!-- Bouncy Castle for PKCS#7 generation -->
<dependency>
<groupId>org.bouncycastle</groupId>
<artifactId>bcprov-jdk18on</artifactId>
<version>1.78</version>
</dependency>
<dependency>
<groupId>org.bouncycastle</groupId>
<artifactId>bcpkix-jdk18on</artifactId>
<version>1.78</version>
</dependency>
Compile and Run:
# Compile (with Bouncy Castle in classpath)
javac -cp "ankasecure-sdk-3.0.0.jar:bcprov-jdk18on-1.78.jar:bcpkix-jdk18on-1.78.jar:." ExampleScenario26.java
# Run
java -cp "ankasecure-sdk-3.0.0.jar:bcprov-jdk18on-1.78.jar:bcpkix-jdk18on-1.78.jar:." \
co.ankatech.ankasecure.sdk.examples.ExampleScenario26
Expected Output:
===== SCENARIO 26: PKCS#7 TO JOSE MIGRATION =====
Purpose: Migrate legacy PKCS#7 SignedAndEnvelopedData to modern JOSE with PQC
Pattern: Legacy RSA-2048 → Modern ML-KEM-768
╔═══════════════════════════════════════════════════════════════╗
║ PHASE 1: GENERATE LEGACY PKCS#7 TEST DATA ║
╚═══════════════════════════════════════════════════════════════╝
[Step 1/4] Generating RSA-2048 key pair (Bouncy Castle)...
RSA key pair generated
[Step 2/4] Creating self-signed X.509 certificate...
Certificate DN: CN=Legacy PKCS7 Demo,O=AnkaSecure,C=US
[Step 3/4] Creating PKCS#7 SignedData (inner layer)...
SignedData created (algorithm: SHA256withRSA)
[Step 4/4] Creating PKCS#7 EnvelopedData (outer layer)...
EnvelopedData created (algorithm: RSA-OAEP + AES-256-CBC)
PKCS#7 file written: temp_files/scenario26_legacy.p7m
Legacy PKCS#7 file generated: temp_files/scenario26_legacy.p7m
Format: SignedAndEnvelopedData (nested structure)
╔═══════════════════════════════════════════════════════════════╗
║ PHASE 2: IMPORT LEGACY RSA KEY ║
╚═══════════════════════════════════════════════════════════════╝
[Step 5/11] Converting RSA key to PKCS#12 format...
PKCS#12 created and Base64 encoded
[Step 6/11] Importing RSA key to AnkaSecure...
Key ID: sc26_rsa_legacy_1735152000000
╔═══════════════════════════════════════════════════════════════╗
║ PHASE 3: DECRYPT AND VERIFY PKCS#7 ║
╚═══════════════════════════════════════════════════════════════╝
[Step 7/11] Decrypting PKCS#7 EnvelopedData (outer layer)...
EnvelopedData decrypted
[Step 8/11] Verifying PKCS#7 SignedData (inner layer)...
Signature verified: ✅ VALID
Plaintext extracted to: temp_files/scenario26_pkcs7_extracted.txt
╔═══════════════════════════════════════════════════════════════╗
║ PHASE 4: MIGRATE TO MODERN JOSE WITH PQC ║
╚═══════════════════════════════════════════════════════════════╝
[Step 9/11] Generating ML-KEM-768 key for modern encryption...
Key ID: sc26_kem_modern_1735152000100
Algorithm: ML-KEM-768 (NIST FIPS 203 post-quantum)
[Step 10/11] Encrypting with JOSE (JWE format)...
JOSE file: temp_files/scenario26_jose.enc
╔═══════════════════════════════════════════════════════════════╗
║ PHASE 5: VALIDATE MIGRATION ║
╚═══════════════════════════════════════════════════════════════╝
[Step 11/11] Validating migration...
JOSE decrypted
Validation Results:
• PKCS#7 extraction: ✅ VALID
• JOSE round-trip: ✅ VALID
╔═══════════════════════════════════════════════════════════════╗
║ ✅ SCENARIO 26 SUCCESSFUL ║
║ ║
║ Legacy PKCS#7 successfully migrated to modern JOSE: ║
║ • PKCS#7 SignedAndEnvelopedData decrypted and verified ║
║ • Content migrated to JOSE (JWE) with ML-KEM-768 ║
║ • Plaintext integrity maintained throughout migration ║
║ ║
║ Migration path: RSA-2048 (Legacy) → ML-KEM-768 (PQC) ║
╚═══════════════════════════════════════════════════════════════╝
===== SCENARIO 26 END =====
Key Concepts
PKCS#7/CMS Overview
PKCS#7 (Cryptographic Message Syntax) is a standard for digitally signed and/or encrypted data:
SignedData: Contains signature over plaintext
EnvelopedData: Contains encrypted content for recipients
SignedAndEnvelopedData: Nested structure - signature inside encryption
Migration Benefits
| Aspect | PKCS#7 (Legacy) | JOSE (Modern) |
|---|---|---|
| Format | ASN.1/DER binary | JSON text |
| Algorithms | RSA, AES (classical only) | RSA, ML-KEM, ML-DSA (PQC ready) |
| Tooling | Bouncy Castle, OpenSSL | Native JWT libraries, easier integration |
| Web compatibility | Requires encoding | Native JSON |
| Future-proof | Quantum-vulnerable | Post-quantum capable |
Bouncy Castle Dependency
This example requires Bouncy Castle for PKCS#7 generation (legacy side only):
- Modern JOSE operations use AnkaSecure SDK (no Bouncy Castle needed)
- PKCS#7 parsing in production would use
POST /api/migration/analyze-pkcs7 - PKCS#7 conversion in production uses
POST /api/migration/convert-pkcs7-to-jose
Related Examples
- Flow 13 - PKCS#12 Import & Hybrid Crypto (key import only)
- Flow 25 - External Key Interoperability (B2B encryption)
- Flow 4 - RSA→ML-KEM Re-encrypt Streaming (algorithm migration)
Note: For the complete 471-line implementation with full Bouncy Castle PKCS#7 generation code, helper methods, and X.509 certificate creation, refer to the source file in the SDK.