当前位置: 首页 > 知识库问答 >
问题:

Java-使用现有公钥文件加密字符串

蒋芷阳
2023-03-14

在过去的4-5个小时里,我一直在研究这个问题,尽管找到了从几个方法到整个100行课程的“答案”,但似乎找不到一个真正有效的答案。我无法想象,没有什么简单的函数可以做这样一件小事:P

我有一组预先存在的公钥/私钥(实际上,两组-一组由ssh-keygen生成,另一组由openssl生成,所以...

我所追求的只是一个简单的java,相当于我用python编写的东西-

key_object = someModule.KeyObject(nameOfPublicKeyFile)

def encrypt (SomePlainText) :
  return someOtherModule.encrypt(key_object, SomePlainText)

任何帮助都会很棒!

共有3个答案

范哲
2023-03-14

这是一个很好的例子:

  • http://javadigest.wordpress.com/2012/08/26/rsa-encryption-example/

还有更多。(如果此链接中断,Google会提供“java加密RSA示例”。)

我似乎找不到一个有效的答案

试试上面链接的那个。如果它不起作用,请跟进编辑或评论来说明出了什么问题。

我无法想象,没有任何简单的函数可以完成这样一件小事P

很抱歉,但是你的想象力一定被打破了:-)

事实上,这不是一件小事。Java正试图使用一个统一的API来支持广泛的加密功能和加密技术堆栈,这一事实使它变得更加困难。

董光霁
2023-03-14

我想分享一段代码...实际上是一个完整的类,如果您根据自己的需要对其进行自定义,它可以做您需要的事情。我在我的一个应用程序中使用了它,我曾经使用生成的公钥/私钥加密/解密文件。同样也可以应用于字符串。

import java.security.*;
import java.security.spec.*;
import javax.crypto.*;
import javax.crypto.spec.*;
import java.io.*;
import java.util.*;

/**
 *  This class encrypts and decrypts a file using CipherStreams
 *  and a 256-bit Rijndael key. The key is then encrypted using
 *  a 1024-bit RSA key, which is password-encrypted.
 */
public class FileEncryptorRSA {
  /**
   *    When files are encrypted, this will be appended to the end
   *    of the filename.
   */
  private static final String ENCRYPTED_FILENAME_SUFFIX=".encrypted";

  /**
   *    When files are decrypted, this will be appended to the end
   *    of the filename.
   */
  private static final String DECRYPTED_FILENAME_SUFFIX=".decrypted";

  /**
   *    Number of times the password will be hashed with MD5
   *    when transforming it into a TripleDES key.
   */
  private static final int ITERATIONS = 1000;

  /**
   *    FileEncryptor is started with one of three options:
   *
   *    -c: create key pair and write it to 2 files
   *    -e: encrypt a file, given as an argument
   *    -d: decrypt a file, given as an argument
   */
  public static void main (String[] args)
  throws Exception {
    if ((args.length < 1) || (args.length > 2)) {
      usage();
    } else if ("-c".equals(args[0])) {
      createKey();
    } else if ("-e".equals(args[0])) {
      encrypt(args[1]);
    } else if ("-d".equals(args[0])) {
      decrypt(args[1]);
    } else {
      usage();
    }
  }

  private static void usage() {
    System.err.println("Usage: java FileEncryptor -c|-e|-d [filename]");
    System.exit(1);
  }

  /**
   *    Creates a 1024 bit RSA key and stores it to
   *    the filesystem as two files.
   */
  private static void createKey()
  throws Exception {
    BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
    System.out.print("Password to encrypt the private key: ");
    String password = in.readLine();
    System.out.println("Generating an RSA keypair...");

    // Create an RSA key
    KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("RSA");
    keyPairGenerator.initialize(1024);
    KeyPair keyPair = keyPairGenerator.genKeyPair();

    System.out.println("Done generating the keypair.\n");

    // Now we need to write the public key out to a file
    System.out.print("Public key filename: ");
    String publicKeyFilename = in.readLine();

    // Get the encoded form of the public key so we can
    // use it again in the future. This is X.509 by default.
    byte[] publicKeyBytes = keyPair.getPublic().getEncoded();

    // Write the encoded public key out to the filesystem
    FileOutputStream fos = new FileOutputStream(publicKeyFilename);
    fos.write(publicKeyBytes);
    fos.close();

    // Now we need to do the same thing with the private key,
    // but we need to password encrypt it as well.
    System.out.print("Private key filename: ");
    String privateKeyFilename = in.readLine();

    // Get the encoded form. This is PKCS#8 by default.
    byte[] privateKeyBytes = keyPair.getPrivate().getEncoded();

    // Here we actually encrypt the private key
    byte[] encryptedPrivateKeyBytes =
    passwordEncrypt(password.toCharArray(),privateKeyBytes);

    fos = new FileOutputStream(privateKeyFilename);
    fos.write(encryptedPrivateKeyBytes);
    fos.close();
  }

  /**
   *    Encrypt the given file with a session key encrypted with an
   *    RSA public key which will be read in from the filesystem.
   */
  private static void encrypt(String fileInput)
  throws Exception {

    BufferedReader in = new BufferedReader
    (new InputStreamReader(System.in));
    System.out.print("Public Key to encrypt with: ");
    String publicKeyFilename = in.readLine();

    // Load the public key bytes
    FileInputStream fis = new FileInputStream(publicKeyFilename);
    ByteArrayOutputStream baos = new ByteArrayOutputStream();

    int theByte = 0;
    while ((theByte = fis.read()) != -1)
    {
      baos.write(theByte);
    }
    fis.close();

    byte[] keyBytes = baos.toByteArray();
    baos.close();

    // Turn the encoded key into a real RSA public key.
    // Public keys are encoded in X.509.
    X509EncodedKeySpec keySpec = new X509EncodedKeySpec(keyBytes);
    KeyFactory keyFactory = KeyFactory.getInstance("RSA");
    PublicKey publicKey = keyFactory.generatePublic(keySpec);

    // Open up an output file for the output of the encryption
    String fileOutput = fileInput + ENCRYPTED_FILENAME_SUFFIX;
    DataOutputStream output = new DataOutputStream
    (new FileOutputStream(fileOutput));

    // Create a cipher using that key to initialize it
    Cipher rsaCipher = Cipher.getInstance("RSA/ECB/PKCS1Padding");
    rsaCipher.init(Cipher.ENCRYPT_MODE, publicKey);

    // Now create a new 256 bit Rijndael key to encrypt the file itself.
    // This will be the session key.
    KeyGenerator rijndaelKeyGenerator = KeyGenerator.getInstance("Rijndael");
    rijndaelKeyGenerator.init(256);
    System.out.println("Generating session key...");
    Key rijndaelKey = rijndaelKeyGenerator.generateKey();
    System.out.println("Done generating key.");

    // Encrypt the Rijndael key with the RSA cipher
    // and write it to the beginning of the file.
    byte[] encodedKeyBytes= rsaCipher.doFinal(rijndaelKey.getEncoded());
    output.writeInt(encodedKeyBytes.length);
    output.write(encodedKeyBytes);

    // Now we need an Initialization Vector for the symmetric cipher in CBC mode
    SecureRandom random = new SecureRandom();
    byte[] iv = new byte[16];
    random.nextBytes(iv);

    // Write the IV out to the file.
    output.write(iv);
    IvParameterSpec spec = new IvParameterSpec(iv);

    // Create the cipher for encrypting the file itself.
    Cipher symmetricCipher = Cipher.getInstance("Rijndael/CBC/PKCS5Padding");
    symmetricCipher.init(Cipher.ENCRYPT_MODE, rijndaelKey, spec);

    CipherOutputStream cos = new CipherOutputStream(output, symmetricCipher);

    System.out.println("Encrypting the file...");

    FileInputStream input = new FileInputStream(fileInput);

    theByte = 0;
    while ((theByte = input.read()) != -1)
    {
      cos.write(theByte);
    }
    input.close();
    cos.close();
    System.out.println("File encrypted.");
    return;
  }

  /**
   *    Decrypt the given file.
   *    Start by getting the RSA private key
   *    and decrypting the session key embedded
   *    in the file. Then decrypt the file with
   *    that session key.
   */
  private static void decrypt(String fileInput)
  throws Exception {

    BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
    System.out.print("Private Key to decrypt with: ");
    String privateKeyFilename = in.readLine();

    System.out.print("Password for the private key: ");
    String password = in.readLine();

    // Load the private key bytes
    FileInputStream fis = new FileInputStream(privateKeyFilename);
    ByteArrayOutputStream baos = new ByteArrayOutputStream();

    int theByte = 0;
    while ((theByte = fis.read()) != -1)
    {
      baos.write(theByte);
    }
    fis.close();

    byte[] keyBytes = baos.toByteArray();
    baos.close();

    keyBytes = passwordDecrypt(password.toCharArray(), keyBytes);

    // Turn the encoded key into a real RSA private key.
    // Private keys are encoded in PKCS#8.
    PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(keyBytes);
    KeyFactory keyFactory = KeyFactory.getInstance("RSA");
    PrivateKey privateKey = keyFactory.generatePrivate(keySpec);

    // Create a cipher using that key to initialize it
    Cipher rsaCipher = Cipher.getInstance("RSA/ECB/PKCS1Padding");

    // Read in the encrypted bytes of the session key
    DataInputStream dis = new DataInputStream(new FileInputStream(fileInput));
    byte[] encryptedKeyBytes = new byte[dis.readInt()];
    dis.readFully(encryptedKeyBytes);

    // Decrypt the session key bytes.
    rsaCipher.init(Cipher.DECRYPT_MODE, privateKey);
    byte[] rijndaelKeyBytes = rsaCipher.doFinal(encryptedKeyBytes);

    // Transform the key bytes into an actual key.
    SecretKey rijndaelKey = new SecretKeySpec(rijndaelKeyBytes, "Rijndael");

    // Read in the Initialization Vector from the file.
    byte[] iv = new byte[16];
    dis.read(iv);
    IvParameterSpec spec = new IvParameterSpec(iv);

    Cipher cipher = Cipher.getInstance("Rijndael/CBC/PKCS5Padding");
    cipher.init(Cipher.DECRYPT_MODE, rijndaelKey, spec);
    CipherInputStream cis = new CipherInputStream(dis, cipher);

    System.out.println("Decrypting the file...");
    FileOutputStream fos = new FileOutputStream(fileInput + DECRYPTED_FILENAME_SUFFIX);

    // Read through the file, decrypting each byte.
    theByte = 0;
    while ((theByte = cis.read()) != -1)
    {
      fos.write(theByte);
    }
    cis.close();
    fos.close();
    System.out.println("Done.");
    return;
  }

  /**
   *    Utility method to encrypt a byte array with a given password.
   *    Salt will be the first 8 bytes of the byte array returned.
   */
  private static byte[] passwordEncrypt(char[] password, byte[] plaintext) throws Exception {

    // Create the salt.
    byte[] salt = new byte[8];
    Random random = new Random();
    random.nextBytes(salt);

    // Create a PBE key and cipher.
    PBEKeySpec keySpec = new PBEKeySpec(password);
    SecretKeyFactory keyFactory = SecretKeyFactory.getInstance("PBEWithSHAAndTwofish-CBC");
    SecretKey key = keyFactory.generateSecret(keySpec);
    PBEParameterSpec paramSpec = new PBEParameterSpec(salt, ITERATIONS);
    Cipher cipher = Cipher.getInstance("PBEWithSHAAndTwofish-CBC");
    cipher.init(Cipher.ENCRYPT_MODE, key, paramSpec);

    // Encrypt the array
    byte[] ciphertext = cipher.doFinal(plaintext);

    // Write out the salt, then the ciphertext and return it.
    ByteArrayOutputStream baos = new ByteArrayOutputStream();
    baos.write(salt);
    baos.write(ciphertext);
    return baos.toByteArray();
  }

  /**
   *    Utility method to decrypt a byte array with a given password.
   *    Salt will be the first 8 bytes in the array passed in.
   */
  private static byte[] passwordDecrypt(char[] password, byte[] ciphertext) throws Exception {

    // Read in the salt.
    byte[] salt = new byte[8];
    ByteArrayInputStream bais = new ByteArrayInputStream(ciphertext);
    bais.read(salt,0,8);

    // The remaining bytes are the actual ciphertext.
    byte[] remainingCiphertext = new byte[ciphertext.length-8];
    bais.read(remainingCiphertext,0,ciphertext.length-8);

    // Create a PBE cipher to decrypt the byte array.
    PBEKeySpec keySpec = new PBEKeySpec(password);
    SecretKeyFactory keyFactory = SecretKeyFactory.getInstance("PBEWithSHAAndTwofish-CBC");
    SecretKey key = keyFactory.generateSecret(keySpec);
    PBEParameterSpec paramSpec = new PBEParameterSpec(salt, ITERATIONS);
    Cipher cipher = Cipher.getInstance("PBEWithSHAAndTwofish-CBC");

    // Perform the actual decryption.
    cipher.init(Cipher.DECRYPT_MODE, key, paramSpec);
    return cipher.doFinal(remainingCiphertext);
  }
}

编辑:

要使用此代码,您需要将JVM的Java策略更改为Java加密扩展(JCE)无限制强度权限。可以在此处找到有关JAVA策略更改的所有相关信息

郎曜文
2023-03-14

shell中的这些openssl命令创建RSA密钥对,并将公钥和私钥写入DER格式的文件。

这里,私钥文件没有密码保护(-nocrypt),以保持简单。

$ openssl genrsa -out keypair.pem 2048
Generating RSA private key, 2048 bit long modulus
............+++
................................+++
e is 65537 (0x10001)
$ openssl rsa -in keypair.pem -outform DER -pubout -out public.der
writing RSA key
$ openssl pkcs8 -topk8 -nocrypt -in keypair.pem -outform DER -out private.der

现在您已经有了DER文件,可以在Java中读取它们,并使用KeySpec和KeyFactory创建PublicKey和PrivateKey对象。

public byte[] readFileBytes(String filename) throws IOException
{
    Path path = Paths.get(filename);
    return Files.readAllBytes(path);        
}

public PublicKey readPublicKey(String filename) throws IOException, NoSuchAlgorithmException, InvalidKeySpecException
{
    X509EncodedKeySpec publicSpec = new X509EncodedKeySpec(readFileBytes(filename));
    KeyFactory keyFactory = KeyFactory.getInstance("RSA");
    return keyFactory.generatePublic(publicSpec);       
}

public PrivateKey readPrivateKey(String filename) throws IOException, NoSuchAlgorithmException, InvalidKeySpecException
{
    PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(readFileBytes(filename));
    KeyFactory keyFactory = KeyFactory.getInstance("RSA");
    return keyFactory.generatePrivate(keySpec);     
}

使用公钥和私钥,您可以加密和解密少量数据(适合您的RSA模数)我建议使用OAEP填充。

public byte[] encrypt(PublicKey key, byte[] plaintext) throws NoSuchAlgorithmException, NoSuchPaddingException, InvalidKeyException, IllegalBlockSizeException, BadPaddingException
{
    Cipher cipher = Cipher.getInstance("RSA/ECB/OAEPWithSHA1AndMGF1Padding");   
    cipher.init(Cipher.ENCRYPT_MODE, key);  
    return cipher.doFinal(plaintext);
}

public byte[] decrypt(PrivateKey key, byte[] ciphertext) throws NoSuchAlgorithmException, NoSuchPaddingException, InvalidKeyException, IllegalBlockSizeException, BadPaddingException
{
    Cipher cipher = Cipher.getInstance("RSA/ECB/OAEPWithSHA1AndMGF1Padding");   
    cipher.init(Cipher.DECRYPT_MODE, key);  
    return cipher.doFinal(ciphertext);
}

在这里,它与一个简单的加密和解密结合在一起:

public void Hello()
{
    try
    {
        PublicKey publicKey = readPublicKey("public.der");
        PrivateKey privateKey = readPrivateKey("private.der");
        byte[] message = "Hello World".getBytes("UTF8");
        byte[] secret = encrypt(publicKey, message);
        byte[] recovered_message = decrypt(privateKey, secret);
        System.out.println(new String(recovered_message, "UTF8"));
    }
    catch (Exception e)
    {
        e.printStackTrace();
    }
}
 类似资料:
  • 问题内容: 我已经在过去4-5个小时内进行了研究,尽管找到了从几种方法到整个〜100行类的所有内容的“答案”,但似乎找不到真正 有效 的答案。我无法想象没有一些简单的功能可以完成如此​​琐碎的事情:P 我有一组预先存在的公用/专用密钥(实际上,有两组-一组由ssh-keygen生成,另一组由openssl生成,所以..什么格式都可以用)。 我所追求的只是一个简单的java等效于我在python中编

  • 我有一个RSA公钥证书。我可以使用具有。PEM扩展名或仅将其用作具有以下格式的字符串: 启动RSA公共密钥 {KEY} -----结束RSA公钥----- 我试图使用此密钥向服务器发送加密的JSON。我尝试了许多其他相关堆栈溢出问题的解决方案,但没有一个答案不适合我。这个答案似乎有道理https://stackoverflow.com/a/43534042,但有些东西不能正常工作,可能是因为X50

  • 在那里~我是新来的flutter开发,我试图使用Node.js服务器发送一个公钥到flutter加密密码但是,它就是不工作,我试图通过JSON格式或通过PEM文件的flutter和使用[Flutter]-加密和[Flutter]-simple_rsa库做加密,但它仍然不能工作。我怎么能这么做?请帮忙,多谢。 [Node.js]-使用[Node rsa]创建密钥[Flatter]-使用[encryp

  • 问题内容: 我正在编写一个用于传输文件的小型应用程序,或多或少地将其作为一种学习更多编程加密基础的方法。这个想法是生成一个RSA密钥对,交换公共密钥,并发送AES iv和密钥以进一步解密。我想用接收者的RSA公钥加密AES密钥,如下所示: 然后,我将密钥值写给接收器,并按如下方式解密: 在控制台的另一端,我将其作为输出: 此外,如果我创建一个大小为16的字节数组,并将cipher.doFinal(

  • 问题内容: 我想用我的公钥输入一个字符串(纯文本)。我有一个,作为从服务器发送来的,并创建了一个公共密钥。现在我想使用该键填充文本。我怎样才能做到这一点。我经历了很多堆栈溢出问题,但没有获得任何成功。 我这是怎么创建, 这将创建一个成功。现在我想用这个密钥来加密另一个。我怎样才能做到这一点。 问题答案: 希望这个能对您有所帮助:

  • 刚开始使用PGP,我正在尝试通过C#控制台应用程序加密一个文件。在我的研究中,似乎BouncyCastle是一个更受欢迎的应用。我找到了下面的文章,它看起来很好,除了我只有公钥。http://burnignorance.com/c-coding-tips/pgp-encryption-decryption-in-c/