1

以下のコードを実行すると、復号化された長さが元の長さと異なります。そのため、音声を読み取ることができません。

次のエラーが発生します: 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();
    }

}

}

何か助けて??

4

2 に答える 2

5

このコードは多くの点で壊れています:

  1. 安全でない PRNG を使用しています
  2. pq素数でなければなりません
  3. パディングを使用していません。RSA にはパディングが必要です。できれば OAEP が必要です
  4. タイミング攻撃を受けやすい
  5. RSA は一度に数バイトしか暗号化できません。実際には、実際のデータを RSA で暗号化することはめったにありません。それは遅いです、暗号文のサイズが大きくなります、これには標準化されたモードはありません...
  6. 文字列の乱用。stringからへの変換BigIntegerはナンセンスです。文字列をまったく使用しないでください。バイナリ データを直接操作する必要があります。
  7. 実際の問題ではありませんが、実際にはe、3 や 65537 などの 2 より大きい小さな素数を選択します。これにより、公開鍵操作が大幅に高速化されます。

これを行う方法:

  1. Java のビルトイン RSA を使用する
  2. 新しいランダム AES キーを生成し、RSA で暗号化します
  3. 認証モードで AES を使用して実際のデータを暗号化します (たとえば、AES-GCM)。
  4. 2. と 3. の結果を連結します。
于 2012-12-06T10:20:41.293 に答える
3

あなたは掘り出し物に四角くしながら、車輪を再発明しようとしているようです. Java には組み込みの暗号化 API があり、これを使用することを強くお勧めします。また、どの暗号化をどこで使用するかを完全に把握する必要もあります。

実装以外の重要な問題は、RSAが非常に小さなデータを渡すように設計されていることです。基本的には、メインデータの暗号化を実際に実行するために使用される別のアルゴリズムのキーです。または、これが役立つ場合は別の言い方をします。RSAは、本質的に「暗号化」アルゴリズムではなく、本質的にキーパッシングスキームと考えてください。

あなたがすべき:

また、私や他の人のチュートリアルを読んで、暗号化で何が起こっているのかを実際に理解しようとすることを強くお勧めします. これは非常に複雑な領域であり、基本的な概念を十分に理解せずに「飛び込む」だけでは、安全でないコードを作成する可能性があります。

于 2012-12-06T10:29:28.610 に答える