【问题标题】:An issue with Asymmetric algorithm usage非对称算法使用问题
【发布时间】:2011-12-09 07:46:55
【问题描述】:

我正在尝试使用非对称加密在客户端使用公钥加密消息,并在服务器端使用私钥解密。

解密消息后,它与平台文本不匹配。你能帮我解决这个问题吗?

下面是代码:

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.math.BigInteger;
import java.security.InvalidKeyException;
import java.security.Key;
import java.security.KeyFactory;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.NoSuchAlgorithmException;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.spec.InvalidKeySpecException;
import java.security.spec.RSAPrivateKeySpec;
import java.security.spec.RSAPublicKeySpec;

import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.NoSuchPaddingException;

public class GenerateKeys {

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

    public static void rsaKeyGeneration() {
        KeyPairGenerator kpg = null;
        try {
            kpg = KeyPairGenerator.getInstance("RSA");
        } catch (NoSuchAlgorithmException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        kpg.initialize(1024);
        KeyPair kp = kpg.genKeyPair();
        Key publicKey = kp.getPublic();
        Key privateKey = kp.getPrivate();
        System.out.println("Algo is :" + publicKey.getAlgorithm());

        KeyFactory fact = null;
        try {
            fact = KeyFactory.getInstance("RSA");
        } catch (NoSuchAlgorithmException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        RSAPublicKeySpec pub = null;
        try {
            pub = fact.getKeySpec(publicKey, RSAPublicKeySpec.class);
        } catch (InvalidKeySpecException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        RSAPrivateKeySpec priv = null;
        try {
            priv = fact.getKeySpec(privateKey, RSAPrivateKeySpec.class);
        } catch (InvalidKeySpecException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }

        try {
            saveToFile("C:/public1.key", pub.getModulus(),
                    pub.getPublicExponent());
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        try {
            saveToFile("C:/private1.key", priv.getModulus(),
                    priv.getPrivateExponent());
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }

    }

    PublicKey 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();
            RSAPublicKeySpec keySpec = new RSAPublicKeySpec(m, e);
            KeyFactory fact = KeyFactory.getInstance("RSA");
            PublicKey pubKey = fact.generatePublic(keySpec);
            return pubKey;
        } catch (Exception e) {
            throw new RuntimeException("Spurious serialisation error", e);
        } finally {
            oin.close();
        }
    }

    public byte[] rsaEncrypt(byte[] data) {
        PublicKey pubKey = null;
        try {
            pubKey = readKeyFromFile("C:/public1.key");
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        Cipher cipher = null;
        try {
            cipher = Cipher.getInstance("RSA");
        } catch (NoSuchAlgorithmException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (NoSuchPaddingException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        try {
            cipher.init(Cipher.ENCRYPT_MODE, pubKey);
        } catch (InvalidKeyException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        byte[] cipherData = null;
        try {
            cipherData = cipher.doFinal(data);
        } catch (IllegalBlockSizeException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (BadPaddingException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        System.out
                .println("encrypted card number is :" + cipherData.toString());
        return cipherData;
    }

    PrivateKey readPriKeyFromFile(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();
            RSAPrivateKeySpec keySpec = new RSAPrivateKeySpec(m, e);
            KeyFactory fact = KeyFactory.getInstance("RSA");
            PrivateKey pKey = fact.generatePrivate(keySpec);
            return pKey;
        } catch (Exception e) {
            throw new RuntimeException("Spurious serialisation error", e);
        } finally {
            oin.close();
        }
    }

    public byte[] rsaDecrypt(byte[] sampleText) {
        PrivateKey priKey = null;
        try {
            priKey = readPriKeyFromFile("C:/private1.key");
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        Cipher cipher = null;
        try {
            cipher = Cipher.getInstance("RSA");
        } catch (NoSuchAlgorithmException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (NoSuchPaddingException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        try {
            cipher.init(Cipher.DECRYPT_MODE, priKey);
        } catch (InvalidKeyException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        byte[] cipherData = null;
        try {
            cipherData = cipher.doFinal(sampleText);
            // cipherData = cipher.
        } catch (IllegalBlockSizeException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (BadPaddingException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        return cipherData;
    }

    public static void main(String s[]) {
        System.out
                .println("++++++++++++++++++++ Program to create the Keys+++++++++++++++++++++++++++++");
        rsaKeyGeneration();
        String sText = "HRB";
        System.out.println("Plain Text Card Number :" + sText);
        GenerateKeys keys = new GenerateKeys();
        byte[] encryptedCardNo = keys.rsaEncrypt(sText.getBytes());
        byte[] decryptedCardNo = keys.rsaDecrypt(encryptedCardNo);
        System.out.println("Decrypted card number is :"
                + decryptedCardNo.toString());

    }
}

【问题讨论】:

  • 这里有一些提示,请将其标记为已关闭。

标签: java encryption cryptography


【解决方案1】:

这很正常,因为您使用的是toString() 方法,该方法返回了一个糟糕的表示。因此,您应该使用十六进制表示来显示加密和解密的文本。这是一个完成工作的函数:

public String byteArrayToHexString(byte[] bArray){
    StringBuffer buffer = new StringBuffer();

    for(byte b : bArray) {
      buffer.append(Integer.toHexString(b));
      buffer.append(" ");
    }

    return buffer.toString();    
}

【讨论】:

    【解决方案2】:

    使用 String.getBytes(Charset): byte[] 和 new String(byte[], Charset): String 方法代替 toString()。 toString() 只会为您提供对字节数组的引用。作为字符集,请使用 Charset.forName("UTF-8"),它始终受到任何 Java 兼容平台(以及 Apache Harmony 很可能)的支持。

    private static final Charset UTF8 = Charset.forName("UTF-8");
    

    ...

    System.out.println(new String("Hi there!".getBytes(UTF8), UTF8));
    

    【讨论】:

    • 但是,在任何情况下,您都不应尝试从加密产生的字节数组构造字符串实例。每个字符集仅支持所有可能代码的一个子集,但密码输出可以是完全任意的。
    • 感谢 GregS 的加入。这是关于显示解密后的数据,所以我没有提及。
    猜你喜欢
    • 2022-09-30
    • 2018-04-25
    • 2014-12-10
    • 2021-05-30
    • 1970-01-01
    • 2019-08-05
    • 2021-11-06
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多