Java 安全性 - RSA 公钥和私钥代码问题

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/18757114/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-12 10:47:59  来源:igfitidea点击:

Java Security - RSA Public Key & Private Key Code Issue

javasecurityencryptionrsa

提问by Priyan RockZ

Here is my error

这是我的错误

java.security.spec.InvalidKeySpecException: java.security.InvalidKeyException: IOException: DerInputStream.getLength(): lengthTag=127, too big.
    at sun.security.rsa.RSAKeyFactory.engineGeneratePublic(Unknown Source)
    at java.security.KeyFactory.generatePublic(Unknown Source)
    at com.sanjaya.rsa.PublicKeyReader.get(PublicKeyReader.java:22)
    at com.sanjaya.rsa.MainKeyClass.main(MainKeyClass.java:8)
Caused by: java.security.InvalidKeyException: IOException: DerInputStream.getLength(): lengthTag=127, too big.
    at sun.security.x509.X509Key.decode(Unknown Source)
    at sun.security.x509.X509Key.decode(Unknown Source)
    at sun.security.rsa.RSAPublicKeyImpl.<init>(Unknown Source)
    at sun.security.rsa.RSAKeyFactory.generatePublic(Unknown Source)
    ... 4 more

Here is my code - MAIN CLASS

这是我的代码 -主类

public static void main(String[] args) {
    PublicKeyReader publicKeyReader=new PublicKeyReader();
    try {
        publicKeyReader.get("c:\public.key");
    } catch (Exception e) {
        e.printStackTrace();
    }

    PrivateKeyReader privateKeyReader=new PrivateKeyReader();
    try {
        privateKeyReader.get("c:\private.key");
    } catch (Exception e) {
        e.printStackTrace();
    }

Here is public key related method

这是公钥相关的方法

  public static PublicKey get(String filename) throws Exception {
    File f = new File(filename);
    FileInputStream fis = new FileInputStream(f);
    DataInputStream dis = new DataInputStream(fis);
    byte[] keyBytes = new byte[(int)f.length()];
    dis.readFully(keyBytes);
    dis.close();
    X509EncodedKeySpec spec =new X509EncodedKeySpec(keyBytes);
    KeyFactory kf = KeyFactory.getInstance("RSA");
    return kf.generatePublic(spec);
  }

Here is private key related method

这里是私钥相关的方法

  public static PrivateKey get(String filename)throws Exception {
    File f = new File(filename);
    FileInputStream fis = new FileInputStream(f);
    DataInputStream dis = new DataInputStream(fis);
    byte[] keyBytes = new byte[(int)f.length()];
    dis.readFully(keyBytes);
    dis.close();
    PKCS8EncodedKeySpec spec =new PKCS8EncodedKeySpec(keyBytes);
    KeyFactory kf = KeyFactory.getInstance("RSA");
    return kf.generatePrivate(spec);
  }

Please help me to sort out this issue

请帮我解决这个问题

Need to create public key & private key & Encrypt ,decrypt string from those under RSA encyption

需要创建公钥 & 私钥 & 加密, 解密来自 RSA 加密下的字符串

采纳答案by Shankar Murthy

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.BufferedReader;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.FileReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.math.BigInteger;
import java.security.Key;
import java.security.KeyFactory;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.spec.KeySpec;
import java.security.spec.RSAPrivateKeySpec;
import java.security.spec.RSAPublicKeySpec;
import javax.crypto.Cipher;
import javax.crypto.CipherInputStream;
import javax.crypto.CipherOutputStream;

class RSA{

public static void main(String[] args) throws Exception {
    generateKeys();
    rsaEncrypt("plaintext.txt", "encrypted.txt");
    rsaDecrypt("encrypted.txt", "decrypted.txt");
}

public static void generateKeys() throws Exception {
    KeyPairGenerator kpg = KeyPairGenerator.getInstance("RSA");
    kpg.initialize(2048);
    KeyPair kp = kpg.genKeyPair();
    PublicKey publicKey = kp.getPublic();
    PrivateKey privateKey = kp.getPrivate();

    System.out.println("keys created");

    KeyFactory fact = KeyFactory.getInstance("RSA");
    RSAPublicKeySpec pub = fact.getKeySpec(publicKey,
            RSAPublicKeySpec.class);
    RSAPrivateKeySpec priv = fact.getKeySpec(privateKey,
            RSAPrivateKeySpec.class);

    saveToFile("public.key", pub.getModulus(), pub.getPublicExponent());
    saveToFile("private.key", priv.getModulus(), priv.getPrivateExponent());

    System.out.println("keys saved");
}

public static void saveToFile(String fileName, BigInteger mod,
        BigInteger exp) throws IOException {
    ObjectOutputStream fileOut = new ObjectOutputStream(
            new BufferedOutputStream(new FileOutputStream(fileName)));
    try {
        fileOut.writeObject(mod);
        fileOut.writeObject(exp);
    } catch (Exception e) {
        throw new IOException("Unexpected error");
    } finally {
        fileOut.close();
        System.out.println("Closed writing file.");
    }
}

// Return the saved key
static Key readKeyFromFile(String keyFileName) throws IOException {
    InputStream in = new FileInputStream(keyFileName);
    ObjectInputStream oin = new ObjectInputStream(new BufferedInputStream(
            in));
    try {
        BigInteger m = (BigInteger) oin.readObject();
        BigInteger e = (BigInteger) oin.readObject();
        KeyFactory fact = KeyFactory.getInstance("RSA");
        if (keyFileName.startsWith("public"))
            return fact.generatePublic(new RSAPublicKeySpec(m, e));
        else
            return fact.generatePrivate(new RSAPrivateKeySpec(m, e));
    } catch (Exception e) {
        throw new RuntimeException("Spurious serialisation error", e);
    } finally {
        oin.close();
        System.out.println("Closed reading file.");
    }
}

// Use this PublicKey object to initialize a Cipher and encrypt some data
public static void rsaEncrypt(String file_loc, String file_des)
        throws Exception {
    FileReader file = new FileReader("C://myprograms//plaintext.txt");
    BufferedReader reader = new BufferedReader(file);
    String text = "";
    String line = reader.readLine();
    while(line!= null)
    {
        text += line;
    line = reader.readLine();
    }
    reader.close();
    System.out.println(text);
    byte[] data = new byte[32];
    int i;

    System.out.println("start encyption");
    Key pubKey = readKeyFromFile("public.key");
    Cipher cipher = Cipher.getInstance("RSA");
    cipher.init(Cipher.ENCRYPT_MODE, pubKey);

    FileInputStream fileIn = new FileInputStream(file_loc);
    FileOutputStream fileOut = new FileOutputStream(file_des);
    CipherOutputStream cipherOut = new CipherOutputStream(fileOut, cipher);

    // Read in the data from the file and encrypt it
    while ((i = fileIn.read(data)) != -1) {
        cipherOut.write(data, 0, i);
    }

    // Close the encrypted file
    cipherOut.close();
    fileIn.close();

    System.out.println("encrypted file created");
}

// Use this PublicKey object to initialize a Cipher and decrypt some data
public static void rsaDecrypt(String file_loc, String file_des)
        throws Exception {
    byte[] data = new byte[32];
    int i;

    System.out.println("start decyption");

    Key priKey = readKeyFromFile("private.key");
    Cipher cipher = Cipher.getInstance("RSA");
    cipher.init(Cipher.DECRYPT_MODE, priKey);

    FileInputStream fileIn = new FileInputStream(file_loc);
    CipherInputStream cipherIn = new CipherInputStream(fileIn, cipher);
    FileOutputStream fileOut = new FileOutputStream(file_des);

    // Write data to new file
    while ((i = cipherIn.read()) != -1) {
        fileOut.write(i);
    }

    // Close the file
    fileIn.close();
    cipherIn.close();
    fileOut.close();

    System.out.println("decrypted file created");

}
}

This program encrypts the text in plaintext.txt file and saves the cipher text in encrypted.txt file. Similarly decryption is done using encrypted.txt file and plain text is saved in decrypted.txt file .#

该程序对plaintext.txt 文件中的文本进行加密,并将密文保存在encrypted.txt 文件中。类似的解密是使用encrypted.txt文件完成的,纯文本保存在decrypted.txt文件中。#

回答by Greg

Check the cert file's newline characters! I had a cert with Unix-style newline chars. I was attempting to use gradle to bundle my cert into a WAR, and I was also having gradle do some string replacements on the files in my WAR. However, gradle was converting everything it processed to Windows-style newline chars. This caused the InvalidKeyException. Excluding my cert files from gradle's processing fixed the problem:

检查证书文件的换行符!我有一个带有 Unix 样式换行符的证书。我试图使用 gradle 将我的证书捆绑到一个 WAR 中,并且我还让 gradle 对我的 WAR 中的文件进行一些字符串替换。但是,gradle 正在将它处理的所有内容转换为 Windows 样式的换行符。这导致了 InvalidKeyException。从 gradle 的处理中排除我的证书文件解决了这个问题:

webInf {
    from myProjectFiles eachFile { projectFile
        if (!projectFile.path.contains( myCertFiles ) {
            filter { line ->
                line.replace(someKey, someValue)
            }
        }
    }
archiveName = 'myProject.war'