簡體   English   中英

如何解密從服務器收到的圖像

[英]how to decrypt image received from server

就我而言,我已經生成了RSA密鑰對和AES密鑰。 我使用AES密鑰加密了圖像,然后使用RSA公鑰進一步加密了圖像。 要解密圖像,我將必須使用RSA私鑰來解密AES密鑰,而AES密鑰又將用於解密圖像。 問題是,如果僅是一段代碼,我知道該怎么做,而現在我只有2條代碼,所以我不確定如何解密從服務器下載到客戶端的圖像。

以下代碼將允許客戶端從服務器下載圖像,但是由於圖像已加密,因此無法打開。

服務器.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();
        }
    }
}

客戶端.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();
        }
    }
}

您完全忽略了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);

對於工作和適當的示例,您可以閱讀例如https://gusto77.wordpress.com/2017/10/30/encryption-reference-project/

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM