繁体   English   中英

使用RSA进行音频加密

[英]Audio Encryption Using RSA

当我运行以下代码时,解密后的长度与原始长度不同。 因此无法读取音频。

我收到此错误:javax.sound.sampled.UnsupportedAudioFileException:无法从输入流中获取音频输入流

at javax.sound.sampled.AudioSystem.getAudioInputStream(AudioSystem.java:1119)
at MainClass.main(MainClass.java:119)

我的代码在这里:

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.math.BigInteger;
import java.util.ArrayList;
import java.util.List;
import java.util.Random;

import javax.sound.sampled.AudioFileFormat;
import javax.sound.sampled.AudioInputStream;
import javax.sound.sampled.AudioSystem;

public class MainClass {
public static final int SIZE = 1024;

private BigInteger p, q, n, totient, e, d;
private Random rnd = new Random();

public MainClass() {

    p = new BigInteger(1024, 10, new Random());
    do {
        q = new BigInteger(1024, 10, new Random());
    } while (p.equals(q));

    n = p.multiply(q);

    totient = (p.subtract(BigInteger.ONE)).multiply(q
            .subtract(BigInteger.ONE));

    // System.out.println(p+"\n"+q+"\n"+n+"\n"+totient);
}

public BigInteger getMod() {
    d = e.modInverse(totient);
    // System.out.println("d="+d);
    return d;
}

public BigInteger getE() {
    do {
        e = new BigInteger(SIZE, rnd);
    } while (!e.gcd(totient).equals(BigInteger.ONE)
            || !(e.compareTo(totient) < 0));
    return e;
}

public String encrypt(String msg) {
    BigInteger ciphertext = new BigInteger(msg.getBytes());
    String cipher = (ciphertext).modPow(getE(), getN()).toString();
    return cipher;
}

public String decrypt(String msg) {
    byte[] decryptMsg = (new BigInteger(msg)).modPow(getMod(), getN())
            .toByteArray();
    String plain = new String(decryptMsg);
    return plain;
}

public BigInteger getN() {
    return n;
}

public static void main(String[] args) {

    try {
        List<String> ori = new ArrayList<String>();
        List<String> st1 = new ArrayList<String>();
        List<String> st2 = new ArrayList<String>();
        String s2;

        MainClass mc = new MainClass();
        // StringHelper sh = new StringHelper();
        byte[] input;
        final ByteArrayOutputStream byteOut = new ByteArrayOutputStream();
        // final AudioFileFormat.Type [] types =
        // AudioSystem.getAudioFileTypes();
        final String PATH = "C:\\Users\\Rahul\\Desktop\\adios.wav";
        final AudioInputStream audioInputStream = AudioSystem
                .getAudioInputStream(new File(PATH));

        AudioSystem.write(audioInputStream, AudioFileFormat.Type.WAVE,
                byteOut);
        audioInputStream.close();
        byteOut.close();
        input = ((ByteArrayOutputStream) byteOut).toByteArray();
        System.out.println(input.length);

        input.toString();
        String s = new String(input);
        System.out.println("Original " + s.length() + "\n");

        int i = 0;
        for (i = 0; i + 255 < s.length(); i = i + 256) {
            ori.add(s.substring(i, i + 255));
        }
        ori.add(s.substring(i - 256, s.length() - 1));
        // System.out.println(s.length());
        for (i = 0; i < ori.size(); i++) {
            st1.add(mc.encrypt(ori.get(i)));
        }
        // String s1 = mc.encrypt(s.substring(0, 500));

        // System.out.println("Cipher Text");
        // System.out.println(s1.length()+ "\n"+s1);
        for (i = 0; i < st1.size(); i++) {
            st2.add(mc.decrypt(st1.get(i)));
        }
        // String s2 = mc.decrypt(s1);
        StringBuffer sb = new StringBuffer();
        for (i = 0; i < st2.size(); i++) {
            sb.append(st2.get(i));
        }
        s2 = sb.toString();
        System.out.println("Decrypt" + s2.length() + "\n");
        byte[] output = s2.getBytes();
        ByteArrayInputStream oInstream = new ByteArrayInputStream(output);
        AudioInputStream oAIS = AudioSystem.getAudioInputStream(oInstream);
        AudioSystem.write(oAIS, AudioFileFormat.Type.WAVE, new File(
                "E:\\decrypted.wav"));
        oAIS.close();
        oInstream.close();
    } catch (Exception e) {
        e.printStackTrace();
    }

}

}

有帮助吗?

这段代码在很多方面都被破坏了:

  1. 您使用的是不安全的PRNG
  2. pq应该是质数
  3. 您没有使用填充。 RSA需要填充,最好是OAEP
  4. 您可以定时攻击
  5. RSA一次只能加密几个字节。 实际上,我们很少使用RSA加密实际数据。 它很 ,它增加了密文的大小,对此没有标准化的模式,...
  6. 滥用字符串。 stringBigInteger转换是胡说八道。 您根本不应该使用字符串,而应该直接使用二进制数据。
  7. 这不是一个真正的问题,但是在实践中,我们选择e作为大于2的小质数,例如3或65537。这将大大加快公共密钥操作的速度。

您应该如何做:

  1. 使用Java内置的RSA
  2. 生成一个新的随机AES密钥并使用RSA对其进行加密
  3. 在身份验证模式下使用AES加密实际数据(例如AES-GCM)
  4. 合并2.和3.的结果。

您似乎正在尝试重新发明轮子,同时使其与讨价还价成直角。 Java有一个内置的加密API,我强烈建议您使用。 而且,您还需要全面了解在哪里使用哪种加密。

除了实现之外,您还有一个关键问题,那就是RSA设计用于传递很小的数据-本质上,这是另一种实际上用于执行主数据加密的算法的密钥。 或者,如果有帮助,可以换一种说法:将RSA本质上看作是密钥传递方案,而不是本身的“加密”算法。

你应该:

  • 使用标准的加密库,使用对称算法(例如AES)对数据进行加密:例如,请参阅我的Java对称/ AES加密教程。
  • 仅将RSA用作将用于加密数据的(AES等)密钥传递给远程客户端的一种方式:再次,我已经在Java中使用示例代码编写了有关使用RSA的文章

我也非常鼓励您通读我的和其他人的教程,以真正尝试并了解加密技术的发展。 这是一个非常复杂的领域,只是对某些基本概念没有很好的理解就可能导致您编写不安全的代码。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM