我必须用ECC加密bmp图像,但是我发现这非常困难,尤其是当像素将映射到椭圆曲线上时,我一点也不了解。因此,我研究了其他选择并发现了ECIES。
我尝试使用bouncycastle在Java中实现它,但是它的工作原理是我的代码将图像加密为文件,但是我去加密了图像的像素并获得了新的加密图像,因此我可以计算出加密和未加密图像之间的PSNR。 我尝试单独加密每个像素,而不是创建加密图像,但是没有用。 是否有某些功能可以帮助我或不列颠哥伦比亚省的任何事情?或者我必须在没有它的情况下实现ECIES?
这是我尝试过的:
Security.addProvider(new org.bouncycastle.jce.provider.BouncyCastleProvider());
KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("EC", "BC");
ECNamedCurveParameterSpec curveParameterSpec = ECNamedCurveTable.getParameterSpec("secp384r1");
keyPairGenerator.initialize(curveParameterSpec, new SecureRandom());
KeyPair KeyPair = keyPairGenerator.generateKeyPair();
ECPublicKey publicKey = (ECPublicKey) KeyPair.getPublic();
ECPrivateKey privateKey = (ECPrivateKey) KeyPair.getPrivate();
javax.crypto.Cipher c1 = javax.crypto.Cipher.getInstance("ECIES", "BC");
javax.crypto.Cipher c2 = javax.crypto.Cipher.getInstance("ECIES", "BC");
c1.init(ENCRYPT_MODE, publicKey, new SecureRandom());
c2.init(DECRYPT_MODE, privateKey, new SecureRandom());
try{
File bmpFile = new File("C:\\Users\\acer\\Desktop\\py\\6.bmp");
BufferedImage image = ImageIO.read(bmpFile);
// to byte
ByteArrayOutputStream baos=new ByteArrayOutputStream();//length=32 bytes, though its size increases if necessary.
ImageIO.write(image, "bmp", baos );
byte[] b = baos.toByteArray();
byte[] cipherimage = c1.doFinal(b, 0, b.length);
byte[] plainimage = c2.doFinal(cipherimage, 0, cipherimage.length);
bmpFile=new File("C:\\Users\\acer\\Desktop\\py\\encryptedimage.bmp");
FileOutputStream fos = new FileOutputStream(bmpFile);
fos.write(cipherimage);
fos.flush();
fos.close();
bmpFile=new File("C:\\Users\\acer\\Desktop\\py\\decryptedimage.bmp");
FileOutputStream fos1 = new FileOutputStream(bmpFile);
fos1.write(plainimage);
fos1.flush();
fos1.close();
} catch (IOException e){
System.out.println(e.getMessage());
}
答案 0 :(得分:0)
似乎您在做出一些错误的假设,并且您可能想重新考虑/重新考虑您的方法。
以获取新的加密图像。然后计算主题之间的(PSNR)峰值信噪比
BMP图像格式不仅仅包含像素。如前所述,存在头元数据(大小,深度,...),如果您对整个文件进行加密,它将不再有意义(它将不再是bmp)。我想您可以创建新图像并在图像级别逐像素处理像素,而不仅仅是加密输入文件。例: https://www.dyclassroom.com/image-processing-project/how-to-get-and-set-pixel-value-in-java
int p = img.getRGB(x,y);
所以我研究了其他选项并找到了ECIES。
ECIES是一种混合方案,您可以查看以下针对ECIES加密的答案https://gist.github.com/amrishodiq/9821413 。输出将需要包含更多/其他信息,而不仅仅是像素,而且绝对不是您可以打开和比较的任何BMP。
混合加密方案假定数据是通过对称密码加密的(我不确定在这种情况下BC使用哪种密码,如果有人知道,请发表评论),其中加密密钥是使用ECC派生的。
因此,最后,您将比较由基础对称算法(例如aes256-cbc)加密的像素,该算法旨在提供与随机输出无法区分的输出。
必须使用ECC加密bmp图像
如果您要加密每个像素(假设您将每个像素表示为16位rgb),则ECC输出比输入数据长得多,因此将输入值直接映射到相同尺寸的输出并不容易(大小)