openssl -decrypt by Java

前端 未结 2 861
粉色の甜心
粉色の甜心 2021-02-11 10:06

all! I am trying to resolve the issue.

I have bat-file with command:

openssl smime -decrypt -binary -inform DER -recip [path to certificate] -inkey  [pat         


        
相关标签:
2条回答
  • 2021-02-11 10:58

    I've found the solution for my question! Thank you all for your advises.

    I've found the source. Thank you very much to author of this source.

    I implemented it that way:

    package javatest;
    
    import org.bouncycastle.cms.*;
    import org.bouncycastle.cms.jcajce.JceCMSContentEncryptorBuilder;
    import org.bouncycastle.cms.jcajce.JceKeyTransEnvelopedRecipient;
    import org.bouncycastle.cms.jcajce.JceKeyTransRecipientInfoGenerator;
    import org.bouncycastle.jce.provider.BouncyCastleProvider;
    import org.bouncycastle.operator.OutputEncryptor;
    
    import java.io.*;
    import java.nio.file.Files;
    import java.security.*;
    import java.security.cert.CertificateEncodingException;
    import java.security.cert.CertificateException;
    import java.security.cert.CertificateFactory;
    import java.security.cert.X509Certificate;
    import java.util.Collection;
    import java.util.Enumeration;
    import java.util.Iterator;
    
    /**
     *
     * @author kagkarlsson
     * @link https://github.com/kagkarlsson/cms-decrypt-example/blob/master/src/main/java/no/posten/dpost/EncryptAndDecrypt.java
     */
    public class EncryptAndDecrypt {
        public static void decrypt(PrivateKey privateKey, File encrypted, File decryptedDestination) throws IOException, CMSException {
            byte[] encryptedData = Files.readAllBytes(encrypted.toPath());
    
            CMSEnvelopedDataParser parser = new CMSEnvelopedDataParser(encryptedData);
    
            RecipientInformation recInfo = getSingleRecipient(parser);
            Recipient recipient = new JceKeyTransEnvelopedRecipient(privateKey);
    
            try (InputStream decryptedStream = recInfo.getContentStream(recipient).getContentStream()) {
                Files.copy(decryptedStream, decryptedDestination.toPath());
            }
    
            System.out.println(String.format("Decrypted '%s' to '%s'", encrypted.getAbsolutePath(), decryptedDestination.getAbsolutePath()));
        }
    
        public static void encrypt(X509Certificate cert, File source, File destination) throws CertificateEncodingException, CMSException, IOException {
            CMSEnvelopedDataStreamGenerator gen = new CMSEnvelopedDataStreamGenerator();
            gen.addRecipientInfoGenerator(new JceKeyTransRecipientInfoGenerator(cert));
            OutputEncryptor encryptor = new JceCMSContentEncryptorBuilder(CMSAlgorithm.AES256_CBC).setProvider(BouncyCastleProvider.PROVIDER_NAME).build();
    
            try (FileOutputStream fileStream = new FileOutputStream(destination);
                    OutputStream encryptingStream = gen.open(fileStream, encryptor)) {
    
                byte[] unencryptedContent = Files.readAllBytes(source.toPath());
                encryptingStream.write(unencryptedContent);
            }
    
            System.out.println(String.format("Encrypted '%s' to '%s'", source.getAbsolutePath(), destination.getAbsolutePath()));
        }
    
        public static X509Certificate getX509Certificate(File certificate) throws IOException, CertificateException {
            try (InputStream inStream = new FileInputStream(certificate)) {
                CertificateFactory cf = CertificateFactory.getInstance("X.509");
                return (X509Certificate) cf.generateCertificate(inStream);
            }
        }
    
        public static PrivateKey getPrivateKey(File file, String password) throws Exception {
            KeyStore ks = KeyStore.getInstance("PKCS12");
            try (FileInputStream fis = new FileInputStream(file)) {
                ks.load(fis, password.toCharArray());
            }
    
            Enumeration<String> aliases = ks.aliases();
            String alias = aliases.nextElement();
            return (PrivateKey) ks.getKey(alias, password.toCharArray());
        }
    
        private static RecipientInformation getSingleRecipient(CMSEnvelopedDataParser parser) {
            Collection recInfos = parser.getRecipientInfos().getRecipients();
            Iterator recipientIterator = recInfos.iterator();
            if (!recipientIterator.hasNext()) {
                throw new RuntimeException("Could not find recipient");
            }
            return (RecipientInformation) recipientIterator.next();
        }
    }

    and

    package javatest;
    
    import java.io.File;
    import java.io.FileInputStream;
    import java.io.InputStreamReader;
    import java.nio.file.Files;
    import java.security.PrivateKey;
    import java.security.Security;
    import org.bouncycastle.jce.provider.BouncyCastleProvider;
    import org.bouncycastle.openssl.PEMKeyPair;
    import org.bouncycastle.openssl.PEMParser;
    import org.bouncycastle.openssl.jcajce.JcaPEMKeyConverter;
    
    /**
     * Test decrypt file
     *
     * @author a.chernyy
     */
    public class JavaTest {
    
        /**
         * String to hold name of the encryption algorithm.
         */
        public static final String ALGORITHM = "RSA";
    
        /**
         * String to hold the path to the keys' dir.
         */
        public static final String KEYS_DIR = "D:" + File.separator + "keystore" + File.separator;
    
        /**
         * String to hold the name of the private key file.
         */
        public static final String PRIVATE_KEY_FILE = KEYS_DIR + "priv.key";
    
        /**
         * String to hold name of the public key file.
         */
        public static final String CERT_FILE = KEYS_DIR + "cert.cer";
    
        /**
         * String to hold name of the encrypted file.
         */
        public static final String ENCRYPTED_FILE = "D:" + File.separator + "Temp" + File.separator + "encrypted.xml";
    
        /**
         * String to hold name of the decrypted file.
         */
        public static final String DECRYPTED_FILE = "D:" + File.separator + "Temp" + File.separator + "decrypted.xml";
    
        /**
         * @param args the command line arguments
         */
        public static void main(String[] args) {
            try {
                //get private key
                File keyFl = new File(PRIVATE_KEY_FILE);
                Security.addProvider(new BouncyCastleProvider());
                PEMParser pemParser = new PEMParser(new InputStreamReader(new FileInputStream(keyFl)));
                PEMKeyPair pemKeyPair = (PEMKeyPair) pemParser.readObject();
                JcaPEMKeyConverter converter = new JcaPEMKeyConverter().setProvider("BC");
                PrivateKey privateKey = converter.getPrivateKey(pemKeyPair.getPrivateKeyInfo());
                
                //Decrypt file
                File encryptedFile = new File(ENCRYPTED_FILE);
                File decryptedFile = new File(DECRYPTED_FILE);
                Files.deleteIfExists(decryptedFile.toPath());
                Security.addProvider(new BouncyCastleProvider());
                EncryptAndDecrypt.decrypt(privateKey, encryptedFile, decryptedFile);
            } catch (Exception e) {
                System.out.println("It's a pity...");
                System.err.println(e.getMessage());
            }
            System.out.println("THE END");
        }
    
    }

    So, it works! :)

    0 讨论(0)
  • 2021-02-11 11:06

    S/MIME is based on a standard called PKCS #7, the Cryptographic Message Syntax. An S/MIME–encrypted message is not simply the output of an encryption operation; it's a package of meta-data and (optionally) the encrypted content itself. It has to be parsed to find the cipher text, the encrypted content encryption key(s), the algorithm and parameters applied to the content encryption key, the algorithm and parameters applied to the content itself, etc.

    A CMS enveloped-data structure contains information for one or more recipients. Each bundle of recipient information contains an identifier for the recipient and a bit of cipher text encrypted with that recipient's public key. If you have the private key corresponding to one of those recipients, you can decrypt the bit of cipher text, which turns out to be another key for a symmetric cipher. With that, and more meta-data about the symmetric cipher mode and parameters, you can decrypt the actual message itself.

    To decrypt it, you'll need an S/MIME or CMS library. (Library recommendations are off-topic, but you can look at BouncyCastle.)

    0 讨论(0)
提交回复
热议问题