如何解密从服务器收到的图像

时间:2018-02-14 06:30:54

标签: java encryption aes rsa

就我而言,我已经生成了一个RSA密钥对和一个AES密钥。我使用AES密钥加密了图像,该密钥使用RSA公钥进一步加密。为了解密图像,我将不得不使用RSA私钥来解密AES密钥,而AES密钥又将用于解密图像。问题是,如果它只是一段代码,我知道如何做到这一点,现在我有两段代码,所以我不确定我将如何解密下载的图像从服务器到我的客户。

以下代码将允许客户端从服务器下载图像,但图像无法打开,因为它已加密。

Server.java

public class Server {
    public static void main(String[] args) throws Exception {
        ServerSocket serverSocket = new ServerSocket(15123);
        Socket socket = null;
        String path = "C:\\Users\\john\\Documents\\Applied Cryptography\\Assignment 2";

        //start of AES
        //Generate AES Key
        int sizeofkey = 128;
        KeyGenerator kg = KeyGenerator.getInstance("AES");

        //initialize with sizeofkey(aes)
        kg.init(sizeofkey);
        Key mykey = kg.generateKey();
        System.out.println("AES Key Generated");

        //create cipher object & initialize with generated key(aes)
        Cipher cipher = Cipher.getInstance("AES");
        cipher.init(Cipher.ENCRYPT_MODE, mykey);

        //create RSA keypair(rsa)
        KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("RSA");
        keyPairGenerator.initialize(1024);

        //generate RSA keypair(rsa)
        KeyPair keyPair = keyPairGenerator.genKeyPair();

        //split keys(rsa) and store in file
        PublicKey pub = keyPair.getPublic();
        PrivateKey priv = keyPair.getPrivate();
        X509EncodedKeySpec pubkey = new X509EncodedKeySpec(pub.getEncoded());
        FileOutputStream fos = new FileOutputStream(path + "/public.key");
        fos.write(pubkey.getEncoded());
        fos.close();

        //Initialise the RSA cipher with PUBLIC key
        Cipher rsacipher = Cipher.getInstance("RSA/ECB/PKCS1Padding");
        rsacipher.init(Cipher.ENCRYPT_MODE, pub);

        //Get bytes for AES key & encrypt bytes of AES key
        byte[] encryptedKey = mykey.getEncoded();
        byte[] cipherkey = rsacipher.doFinal(encryptedKey);
        System.out.println("AES key Encrypted");

        while (true) {
            socket = serverSocket.accept();
            System.out.println("Accepted connection : " + socket.getRemoteSocketAddress().toString() + " <-> /127.0.0.1:15123");

            OutputStream sos = socket.getOutputStream();

            // get the image from a webcam
            URL myimage = new URL("http://183.76.13.58:80/SnapshotJPEG?Resolution=640x480");

            //Picture in byte array format
            byte[] plainpic = null;
            ByteArrayOutputStream baos = new ByteArrayOutputStream();
            InputStream is = null;
            try {
                //in = new DataInputStream(myimage.openStream());


                is = myimage.openStream();
                byte[] byteChunk = new byte[4096];
                int n;

                while ((n = is.read(byteChunk)) > 0) {
                    baos.write(byteChunk, 0, n);
                }

                //Picture in byte array format
                plainpic = baos.toByteArray();
                System.out.println(plainpic);
            } catch (Exception ee) {
                System.out.println("Check internet connection please");
                socket.close();
                return;
            }
            byte[] cipherpic = cipher.doFinal(plainpic);

            DateFormat dateFormat = new SimpleDateFormat("yy/MM/dd HH:mm:ss");
            Date date = new Date();
            System.out.println("Sending image " + dateFormat.format(date));


            sos.write(cipherpic);
            System.out.println("-------------- Done ----------");

            is.close();
            sos.flush();
            sos.close();
            socket.close();
        }
    }
}

Client.java

public class Client {
    public static void main(String[] args) throws IOException {
        String fname = "image.jpg";
        String path = "C:\\Users\\john\\Documents\\Applied Cryptography\\Assignment 2";
        File pubkeyfile = new File(path + "/public.key");
        FileInputStream fis = new FileInputStream(path + "/public.key");
        byte[] encodedPubKey = new byte[(int) pubkeyfile.length()];
        fis.close();

        Socket socket = new Socket("127.0.0.1", 15123);
        InputStream is = null;
        byte[] isbytearray = null;
        try {

            is = socket.getInputStream();
            ByteArrayOutputStream baos = new ByteArrayOutputStream();
            byte[] byteChunk = new byte[40000];
            int n;

            while ((n = is.read(byteChunk)) > 0) {
                baos.write(byteChunk, 0, n);
            }
            isbytearray = baos.toByteArray();

            //decrypt encrypted byte[], convert decrypted byte[] to bytes
            //how to decrypt?

        } catch (Exception ee) {
            System.out.println("Check connection please");
            socket.close();
            return;
        }

        FileOutputStream fos = new FileOutputStream(fname);
        try {
            //write converted bytes to file to display picture
            fos.write(isbytearray); //this is the encrypted image,not the decrypted one
        } catch (EOFException ee) {
            System.out.println("File transfer complete");
            is.close();
        }
        fos.flush();
        fos.close();
        socket.close();

        public static String asHex ( byte buf[]){

            //Obtain a StringBuffer object
            StringBuffer strbuf = new StringBuffer(buf.length * 2);
            int i;

            for (i = 0; i < buf.length; i++) {
                if (((int) buf[i] & 0xff) < 0x10)
                    strbuf.append("0");
                strbuf.append(Long.toString((int) buf[i] & 0xff, 16));
            }
            // Return result string in Hexadecimal format
            return strbuf.toString();
        }
    }
}

1 个答案:

答案 0 :(得分:0)

你完全忽略了IV(初始化矢量)。

理论上你总是使用一个新密钥,因此它可能是静态的,但是当用RSA加密时,它是随机生成的,你必须保留IV(通常是IV加在密文之前)并在解密时使用该值。即使陈述iv在你的情况下可能是静态的,请养成正确使用它的习惯(随机)iv)

使用AES和显式IV加密

SecureRandom rnd = new SecureRandom();
byte[] iv = new byte[SYMMETRIC_BLOCK_SIZE / 8];
rnd.nextBytes(iv);
encryptionParams.setIv(iv);

IvParameterSpec ivParamSpec = new 
IvParameterSpec(iv);
SecretKey symmetricKey = new 
SecretKeySpec(encryptionParams.getKey(), SYMMETRIC_KEY_ALG);

Cipher cipher = 
Cipher.getInstance(SYMMETRIC_CIPHER_NAME);
cipher.init(Cipher.ENCRYPT_MODE, symmetricKey, ivParamSpec);

然后解密

// encryptionParams is an object I use to pass ciphertext, iv and mac

IvParameterSpec ivParamSpec = new 
IvParameterSpec(encryptionParams.getIv());
// you can read iv as part of the passed data
SecretKey symmetricKey = new 
SecretKeySpec(encryptionParams.getKey(), SYMMETRIC_KEY_ALG);

Cipher cipher = 
Cipher.getInstance(SYMMETRIC_CIPHER_NAME);
cipher.init(Cipher.DECRYPT_MODE, symmetricKey, ivParamSpec);

有关工作和适当的例子,你可以阅读e。 G。 https://gusto77.wordpress.com/2017/10/30/encryption-reference-project/