2016-08-21 10 views
1

リトル背景:私はクリプトパルズの挑戦をしています。私はhttps://cryptopals.com/sets/1/challenges/1を完成しましたが、私は私が推測したことが学ばれる(またはコード化される)ことを学んでいないことを認識しました。Javaでエンコード/デコードのバイトはどのように機能しますか?

私は、HexとBase64エンコーディング/デコードにApache Commons Codecライブラリを使用しています。目標は16進文字列をデコードし、それをBase64に再エンコードすることです。ページの下部にあるヒントには、は「常に生のバイトで動作し、エンコードされた文字列では決して動作しません。かなりの印刷にのみhexとbase64を使用してください。ここで

は、私の答えは...

private static Hex forHex = new Hex(); 
private static Base64 forBase64 = new Base64(); 

public static byte[] hexDecode(String hex) throws DecoderException { 
    byte[] rawBytes = forHex.decode(hex.getBytes()); 
    return rawBytes; 
} 
public static byte[] encodeB64(byte[] bytes) { 
    byte[] base64Bytes = forBase64.encode(bytes); 
    return base64Bytes; 
} 

public static void main(String[] args) throws DecoderException { 

String hex = "49276d206b696c6c696e6720796f757220627261696e206c696b65206120706f69736f6e6f7573206d757368726f6f6d"; 


//decode hex String to byte[] 
byte[] myHexDecoded = hexDecode(hex); 
String myHexDecodedString = new String(myHexDecoded); 

//Lyrics from Queen's "Under Pressure" 
System.out.println(myHexDecodedString); 

//encode myHexDecoded to Base64 encoded byte[] 
byte[] myHexEncoded = encodeB64(myHexDecoded); 
String myB64String = new String(myHexEncoded); 

//"pretty printing" of base64 
System.out.println(myB64String); 

}

だ...しかし、私はだまさような気がします。私は、16進数でエンコードされたバイトをデコードする方法を学びませんでした。そして、純粋なバイトをBase64にエンコードする方法を学んでいませんでした。私はライブラリを使って何かをする方法を学んだだけです。

Javaで文字列を取得してバイトを取得する場合、これらのバイトを16進数でどのようにエンコードしますか?例えば、次のコード切り取り領域が "こんにちは"(読み取り可能な英語である)、各文字のバイト値になる:

String s = "Hello"; 
char[] sChar = s.toCharArray(); 
byte[] sByte = new byte[sChar.length] 
for(int i = 0; i < sChar.length; i++) { 
    sByte[i] = (byte) sChar[i]; 
    System.out.println("sByte[" + i + "] = " +sByte[i]); 
} 

sByteをもたらす[0] = 72、sByte [1] = 101、sByte [ '0 'を例として使用します - 私は10進数のバージョンが111であると推測しています - ちょうどその10進数のバージョンを取ってそれを変更しますか?その16進版に?

もしそうなら、デコードするために、16進数の文字列2の文字を一度に取り出し、小数値に分解してからASCIIに変換しますか?それはいつもASCIIでしょうか?

+0

'(byte)sChar [i]'データが失われています。バイトは8ビット、charは16です。テキストはなくエンコードされたテキストです。文字列は、UTF-16コード単位のカウントされたシーケンスです。各Unicodeコードポイントの1つまたは2つが必要です。バイト配列が必要な場合は、エンコーディングを選択し、それが既知であることを確認します。それから文字列のバイトを与えるようにエンコーディングを尋ねてください。あなたが書くことを学びたいものなら、Javaはあなた自身のエンコーダをこれに入れさせるでしょう。 –

+0

データの損失を指摘していただきありがとうございます。これは、私が挑戦#4で抱えている問題を解決する可能性があります。 – appills

答えて

2

デコードするには、16進数の値に分解してからASCIIに変換するだけです。それはいつもASCIIでしょうか?

いいえ文字を2つずつ取得し、文字「0」を数値0に、文字「1」を数値1に、文字「a」( ...、 'f'または 'F'を数値15に変換します。

次に、最初の数値を乗算しますこれを2番目の数値に加えて、バイトの符号なし整数値を取得します。次に、その符号なし整数値を符号付きバイトに変換します。

ASCIIはこのアルゴリズムとは関係ありません。

実際にどのように行われているかを見るには、commons-codecはオープンソースなので、その実装を見ることができます。

+0

前のコメントは無意味な質問のため削除されました。私はあなたが「最初の数値」によって何を言っているのか理解しています。私はソースコードを見ています、ありがとう! – appills

+0

あなたの答えを受け入れるのにとても時間がかかることを申し訳ありません! – appills

関連する問題