2011-03-22 100 views
2

我正在使用RSA(使用Java)來加密文本。我需要通過電子郵件發送該文本。RSA加密問題

import java.io.BufferedReader; 
import java.io.File; 
import java.io.FileInputStream; 
import java.io.FileNotFoundException; 
import java.io.FileReader; 
import java.io.IOException; 
import java.io.InputStreamReader; 
import java.math.BigInteger; 
import java.nio.Buffer; 
import java.security.KeyFactory; 
import java.security.NoSuchAlgorithmException; 
import java.security.PrivateKey; 
import java.security.PublicKey; 
import java.security.interfaces.RSAPrivateKey; 
import java.security.spec.InvalidKeySpecException; 
import java.security.spec.RSAPrivateKeySpec; 
import java.security.spec.RSAPublicKeySpec; 

import javax.crypto.Cipher; 

public class importarLlaves { 

/** 
    * @param args 
    */ 
public static void main(String[] args) { 
    File archivo = new File("C:/llaves/Publica 2.txt"); 
    File archivo2 = new File("C:/llaves/Privada 2.txt"); 

    try { 

    BufferedReader lector = new BufferedReader(new FileReader(archivo)); 
    String[] linea = lector.readLine().split(":"); 
    String moduloPublico = linea[1]; 
    linea = lector.readLine().split(":"); 
    String exponentePublico = linea[1]; 
    lector.close(); 

    lector = new BufferedReader(new FileReader(archivo2)); 
    lector.readLine(); 
    linea = lector.readLine().split(":"); 
    String exponentePrivado = linea[1]; 
    lector.close(); 

    String algorithm = "RSA"; 
    KeyFactory factory = KeyFactory.getInstance(algorithm); 
    RSAPublicKeySpec publicKeySpec = new RSAPublicKeySpec(new BigInteger(moduloPublico), new BigInteger(exponentePublico)); 
    PublicKey llavePublica = factory.generatePublic(publicKeySpec); 

    RSAPrivateKeySpec privateKeySpec = new RSAPrivateKeySpec(new BigInteger(moduloPublico), new BigInteger(exponentePrivado)); 
    PrivateKey llavePrivada = factory.generatePrivate(privateKeySpec); 

    System.out.println(llavePublica.toString()); 

    System.out.println(llavePrivada.toString()); 

    // Iniciar un objeto para la encr/desencr 
    Cipher desCipher = Cipher.getInstance("RSA"); 

    // Leer, escribir y encriptar un dato 
    BufferedReader stdIn = new BufferedReader(new InputStreamReader(System.in)); 
    String pwd = stdIn.readLine(); 
    byte [ ] cleartext = pwd.getBytes(); 
    String s1 = new String (cleartext); 
    System.out.println ("password original:" + s1);desCipher.init (Cipher.ENCRYPT_MODE, llavePublica); 
    byte [ ] ciphertext = desCipher.doFinal(cleartext); 
    String s2 = new String (ciphertext); 
    System.out.println ("password encriptado:" + s2); 

    // Ahora desencriptar 



    desCipher.init(Cipher.DECRYPT_MODE, llavePrivada); 
    byte [ ] cleartext1 = desCipher.doFinal(ciphertext); 
    String s3 = new String (cleartext1); 
    System.out.println("password desencriptado:"+ s3); 



    } catch (Exception e) { 
    // TODO Auto-generated catch block 
    e.printStackTrace(); 
    } 

} 

} 

這段代碼很好用,但是當我嘗試解密時,它只有在我傳遞原始密文字節時纔有效。

byte [ ] cleartext1 = desCipher.doFinal(ciphertext); 

我需要安全地將加密從字節[]轉換爲字符串(發送它的電子郵件)。但是,如果我嘗試這樣的:

s2.getBytes(); 

它返回從S2字符串(如加密的文本存儲)字節。但是,如果我嘗試使用該字符串傳遞給desCipher(desencrypt),它會失敗,並說:數據不能從0開始。

回答

2

這是我的理解,並非所有字節都可以清楚地編碼爲字符(在String )。在發送之前將其編碼爲base64,然後在解密之前解碼base64字符串。

Apache Commons Codec項目可以編碼/解碼base64。

http://commons.apache.org/codec/

+1

+1,這正是base64的用意。它將確保可以在字符串中正確表示任意字節序列。另外,我還建議在將字節轉換爲字符串或反之時,指定字符集而不是始終使用平臺默認值。 – Peter 2011-03-22 03:22:12

+0

@Peter:提及字符集+1。 – Jonah 2011-03-22 04:08:11

+0

現在我想到了,對於Base64來說,charset可能無關緊要,因爲你總是要用ASCII來獲取字符,但它仍然是一個好習慣。 – Peter 2011-03-22 13:28:40