Difference between revisions of "LlXorBase64StringsCorrect/ja"

From Second Life Wiki
Jump to navigation Jump to search
m (カテゴリ変更)
 
(2 intermediate revisions by one other user not shown)
Line 1: Line 1:
{{LSL_Function/ja
{{Issues/SVC-289|str1|str2}}{{LSL_Function/ja
|func_id=319
|func_id=319
|func_sleep=0.0
|func_sleep=0.0
Line 8: Line 8:
|p1_type=string|p1_name=str1|p1_desc=Base64 文字列
|p1_type=string|p1_name=str1|p1_desc=Base64 文字列
|p2_type=string|p2_name=str2|p2_desc=Base64 文字列
|p2_type=string|p2_name=str2|p2_desc=Base64 文字列
|func_footnote='''str2''' は '''str1''' より短い場合、同じ長さになるよう自動的に繰り返して調整されます。引数が Base64 文字列でない場合、戻り値は突飛なものになるでしょう。<br/>暗号化アルゴリズムを設計する前に [[#ノート|ノート]] を必ず読んでください。
|func_footnote='''str2''' は '''str1''' より短い場合、繰り返されます。引数が Base64 文字列でない場合、戻り値は突飛なものになるでしょう。<br/>暗号化アルゴリズムを設計する前に [[#Cryptography|暗号学]] 節を必ず読んでください。
|func_desc=二つの Base64 文字列の XOR を計算します。
|func_desc=2 つの Base64 文字列の XOR を計算します。
|return_text='''str1''' と '''str2''' を Base64 XOR した文字列
|return_text='''str1''' と '''str2''' を Base64 XOR した文字列
|spec
|spec
|caveats
|caveats=
* バイト配列に変換する過程で、'''str1''' と '''str2''' の両方で最後の <code>(ビット数 % 8)</code> が失われます。詳細は [[#Implementation|実装]] を参照してください。
|constants
|constants
|examples=<lsl>default
|examples=<source lang="lsl2">default
{
{
     state_entry(){
     state_entry(){
Line 34: Line 35:
     }
     }
   
   
}</lsl>
}</source>
|helpers
|helpers
|also_functions
|also_functions
|also_events
|also_events
|also_tests
|also_tests
|also_articles=*[[User:SignpostMarv_Martin/LSL2/llXorBase64StringsCorrect|llXorBase64StringsCorrect in PHP]]
|also_articles=
|notes=
|notes=
===最も良い使い方{{Anchor|Best Practices}}===
===実装{{Anchor|Implementation}}===
暗号化の手法としては XOR は脆弱で、XOR の入力を効率よく求める攻撃手法がいくつかあります。暗号の扱われ方によっては、一つの暗号が破られることによって入力が明らかになり、ひいてはアルゴリズム自身が破られることになります。
XOR は Base64 文字列をバイト配列 '''str1''' と '''str2''' に変換し、それから 2 つのバイト配列を XOR することで動作します。最終的に生成されたバイト配列は Base64 に逆変換され、ユーザに返ります。


パスワードとなる種 (seed) は秘密にしてください。種は XOR で使う前にハッシュ関数でシャッフルし、また時々変更しましょう。
しかし変換の過程でバイト配列の最後の (ビット数 % 8) は失われます。 LSL は Base64 文字列を 8 ビット配列として扱い、 6 ビット配列としては扱いません。


処理の仕組みを知らずに、長さの違う二つの値で XOR を求めてはいけません。一見良い考えに思えるかもしれませんが、それはフィールドをリンクしているだけです。(最小公倍数の長さの) より長い鍵が出来ますが、フィールドがリンクされるため、最小公約数と同じ数のフィールドしかありません。独自のフィールドの数が、攻撃者にとって解読すべき鍵の理論的な最大数を決定します。
===暗号学{{Anchor|Cryptography}}===


Unique_Key_Fields = Greatest_Common_Divisor(lengths_of_keys) * number_of_keys
ここの節で紹介される情報はけっして完全なものではありませんが、読む人に充分な情報を与え、発生するであろう質問を投げかけ、以降を読み進めていくうえで手助けとなるでしょう。暗号学を理解せずして暗号化アルゴリズムを実装しようとしないようにしましょう。さもないと破綻する可能性があります。


===攻撃方針{{Anchor|Attack Vectors}}===
暗号学では、 ''secret'' は暗号化アルゴリズムを変化させるために使われる小さな入力情報のことをいいます。 ''secret'' は何回アルゴリズムが実行されても変化しません。 ''seed'' もアルゴリズムを変化させるために使われますが、 ''secret'' と違い、変化します。変化のしかたはアルゴリズムの一部となっています。
まず、XOR は限定的な文字列暗号だという点に留意してください。
 
secret と seed を効果的に使うためには、少なくとも以下のうちの 2 つは秘密裏に保持する必要があります。 '''1)''' アルゴリズム、 '''2)''' seed 、 '''3)''' secret 。
 
信じられないかもしれませんが、アルゴリズムを秘密にしても安全ではありません。これらのアルゴリズムに対して仕掛ける攻撃ベクトルはアルゴリズムをあまり知らなくても、また全く知らなくても作成できてしまいます。最高の防御は、複数の secret/seed を使用する強いアルゴリズムです。この方法だと、番号付けされたアイテムをカテゴリーとして差し挟むことで、前提条件を満たすことができます。 secret と seed の使われ方を鑑みると、攻撃者がアルゴリズムを破壊するために secret を調べる必要がなく、不変の値と途中経過の値の相互関連さえ調べればよいということになります。変化するコードを不変なコードに翻訳する secret と seed を攻撃者にアクセスさせてはなりません。攻撃者に情報が渡れば渡るほど、アルゴリズムはより単純になるのです。
 
====ベスト・プラクティス{{Anchor|Best Practices}}====
 
暗号化の手法としては XOR は脆弱で、 XOR の入力を効率よく求める攻撃手法がいくつかあります。暗号の扱われ方によっては、一つの暗号が破られることによって入力が明らかになり、ひいてはアルゴリズム自身が破られることになります。
 
パスワードとなる seed は秘密にしてください。 seed は XOR で使う前にハッシュ関数でシャッフルし、また時々変更しましょう。
 
処理の仕組みを知らずに、長さの違う二つの値で XOR を求めてはいけません。一見良い考えに思えるかもしれませんが、それはフィールドをリンクしているだけです。 (最小公倍数の長さの) より長い鍵が出来ますが、フィールドがリンクされるため、最大公約数と同じ数のフィールドしかありません。独自のフィールドの数が、攻撃者にとって解読すべき鍵の理論的な最大数を決定します。
 
ユニークキーのフィールド = 最大公約数(キーの長さ) × キーの数
 
====攻撃ベクトル{{Anchor|Attack Vectors}}====
まず、XOR は貧弱な多表式換字暗号だという点に留意してください。多表式換字暗号に有効な攻撃ベクトルは XOR にも有効です。
* '''確率''': 英語では、各文字の出現頻度は、文法や綴りによって異なります。XOR にはこの出現確率が反映されます。この手法は、鍵が文章よりかなり短い場合にのみ有効です。
* '''確率''': 英語では、各文字の出現頻度は、文法や綴りによって異なります。XOR にはこの出現確率が反映されます。この手法は、鍵が文章よりかなり短い場合にのみ有効です。
* '''UTF-8 ルール''': 文字列を Base64 へ変換するとき、UTF-8 エンコードがまず使われます。入力が有効な UTF-8 文字列と分かっているならば、いくつかのビットを理論的に決定することができます。
* '''UTF-8 ルール''': 文字列を Base64 へ変換するとき、UTF-8 エンコードがまず使われます。入力が有効な UTF-8 文字列と分かっているならば、いくつかのビットを理論的に決定することができます。
* '''平文''': あらかじめ分かっている入力に対する出力が知られてしまうと、鍵には脆弱性が生じます。
* '''平文''': あらかじめ分かっている入力に対する出力が知られてしまうと、鍵には脆弱性が生じます。
* '''総当り''': 鍵、パスワードおよび/あるいは種を攻撃します。
* '''ブルートフォース''': 鍵や secret や seed を攻撃します。


===PHP でのデコード方法===
PHP スクリプトが [http://lslwiki.net/lslwiki/wakka.php?wakka=llXorBase64StringsCorrect LSL Wiki] にあります。
古いバージョンのコードがここにあります: [[User:SignpostMarv_Martin/LSL2/llXorBase64StringsCorrect|llXorBase64StringsCorrect in PHP]]
===Java でのデコード方法===
GET メソッドで送信する際は、必ず BASE64 ハッシュを URLEncode しましょう...
<source lang="java">
      String BASE64datahash = "error";
      String passhash = "error";
      try {
        //URL エンコードされた暗号化済みデータを URLDecode します。
        BASE64datahash = java.net.URLDecoder.decode("KhoFRRYaAUMbEVU%3D", "UTF-8"); //KhoFRRYaAUMbEVU%3D
        System.out.println("BASE64datahash: " + BASE64datahash); //KhoFRRYaAUMbEVU=
        //任意の BASE64 データの配列を作成します。
        char[] BASE64data = BASE64datahash.toCharArray();
        char[] dataUB = new String(new BASE64Decoder().decodeBuffer(new String(BASE64data))).toCharArray(); //データを BASE64 デコードします。
        System.out.println("encrypted data (but base64 decoded) [dataUB]: " + new String(dataUB));
        //秘密鍵・パスワードを BASE64 にエンコードします (BASE64Encoder の使い方を示すためだけのものです)
        //String BASE64password = new String(new BASE64Encoder().encodeBuffer("supersecretpassword".getBytes()));
        //System.out.println("BASE64password: " + new String(BASE64password));
        //BASE64 キー・パスワードの配列を作成します。
        //char[] key = BASE64password.toCharArray();
        //char[] keyUB = new String(new BASE64Decoder().decodeBuffer(new String(key))).toCharArray();
        char[] keyUB = "supersecretpassword".toCharArray();
        System.out.println("plaintext key/password [keyUB]: " + new String(keyUB));
        //データ配列を、対応するキー・パスワードの配列と 1 文字 1 文字 XOR していきます。
        int k=0;
        for (int i = 0; i < dataUB.length; i++) {
            dataUB[i] = (char) (dataUB[i] ^ keyUB[k]);
            k++;
            //キーが短すぎる場合はキーを繰り返します。
            if (k == keyUB.length)
              k=0;
}
        System.out.println("Decoded data [dataUB]: " + new String(dataUB));
       
        } catch (Exception ex) {
            System.out.println("Oops!");
        }
</source>
|permission
|permission
|negative_index
|negative_index
|cat1=Base64/ja
|cat1=Base64
|cat2=Encoding/ja
|cat2=Encoding
|cat3
|cat3
|cat4
|cat4
}}
}}

Latest revision as of 15:52, 25 February 2016

要約

関数: string llXorBase64StringsCorrect( string str1, string str2 );

2 つの Base64 文字列の XOR を計算します。
str1str2 を Base64 XOR した文字列を string で返します。

• string str1 Base64 文字列
• string str2 Base64 文字列

str2str1 より短い場合、繰り返されます。引数が Base64 文字列でない場合、戻り値は突飛なものになるでしょう。
暗号化アルゴリズムを設計する前に 暗号学 節を必ず読んでください。

警告

  • バイト配列に変換する過程で、str1str2 の両方で最後の (ビット数 % 8) が失われます。詳細は 実装 を参照してください。
All Issues ~ Search JIRA for related Bugs

サンプル

default
{
    state_entry(){
        
        // 大文字、小文字、数字、記号を使った複雑なパスワードを使いましょう。
        string pass = "P4s5Wo_rD";
        
        string data = "I am some ver important data.";
        
        // データを暗号化する
        string crypt = llXorBase64StringsCorrect(llStringToBase64(data), llStringToBase64(pass));
        
        // 出来上がった意味不明の文字列を表示
        llOwnerSay(crypt);
        
        // 復号化し、平文を表示
        llOwnerSay(llBase64ToString(llXorBase64StringsCorrect(crypt, llStringToBase64(pass))));
        
    }
 
}

注意点

実装

XOR は Base64 文字列をバイト配列 str1str2 に変換し、それから 2 つのバイト配列を XOR することで動作します。最終的に生成されたバイト配列は Base64 に逆変換され、ユーザに返ります。

しかし変換の過程でバイト配列の最後の (ビット数 % 8) は失われます。 LSL は Base64 文字列を 8 ビット配列として扱い、 6 ビット配列としては扱いません。

暗号学

ここの節で紹介される情報はけっして完全なものではありませんが、読む人に充分な情報を与え、発生するであろう質問を投げかけ、以降を読み進めていくうえで手助けとなるでしょう。暗号学を理解せずして暗号化アルゴリズムを実装しようとしないようにしましょう。さもないと破綻する可能性があります。

暗号学では、 secret は暗号化アルゴリズムを変化させるために使われる小さな入力情報のことをいいます。 secret は何回アルゴリズムが実行されても変化しません。 seed もアルゴリズムを変化させるために使われますが、 secret と違い、変化します。変化のしかたはアルゴリズムの一部となっています。

secret と seed を効果的に使うためには、少なくとも以下のうちの 2 つは秘密裏に保持する必要があります。 1) アルゴリズム、 2) seed 、 3) secret 。

信じられないかもしれませんが、アルゴリズムを秘密にしても安全ではありません。これらのアルゴリズムに対して仕掛ける攻撃ベクトルはアルゴリズムをあまり知らなくても、また全く知らなくても作成できてしまいます。最高の防御は、複数の secret/seed を使用する強いアルゴリズムです。この方法だと、番号付けされたアイテムをカテゴリーとして差し挟むことで、前提条件を満たすことができます。 secret と seed の使われ方を鑑みると、攻撃者がアルゴリズムを破壊するために secret を調べる必要がなく、不変の値と途中経過の値の相互関連さえ調べればよいということになります。変化するコードを不変なコードに翻訳する secret と seed を攻撃者にアクセスさせてはなりません。攻撃者に情報が渡れば渡るほど、アルゴリズムはより単純になるのです。

ベスト・プラクティス

暗号化の手法としては XOR は脆弱で、 XOR の入力を効率よく求める攻撃手法がいくつかあります。暗号の扱われ方によっては、一つの暗号が破られることによって入力が明らかになり、ひいてはアルゴリズム自身が破られることになります。

パスワードとなる seed は秘密にしてください。 seed は XOR で使う前にハッシュ関数でシャッフルし、また時々変更しましょう。

処理の仕組みを知らずに、長さの違う二つの値で XOR を求めてはいけません。一見良い考えに思えるかもしれませんが、それはフィールドをリンクしているだけです。 (最小公倍数の長さの) より長い鍵が出来ますが、フィールドがリンクされるため、最大公約数と同じ数のフィールドしかありません。独自のフィールドの数が、攻撃者にとって解読すべき鍵の理論的な最大数を決定します。

ユニークキーのフィールド = 最大公約数(キーの長さ) × キーの数

攻撃ベクトル

まず、XOR は貧弱な多表式換字暗号だという点に留意してください。多表式換字暗号に有効な攻撃ベクトルは XOR にも有効です。

  • 確率: 英語では、各文字の出現頻度は、文法や綴りによって異なります。XOR にはこの出現確率が反映されます。この手法は、鍵が文章よりかなり短い場合にのみ有効です。
  • UTF-8 ルール: 文字列を Base64 へ変換するとき、UTF-8 エンコードがまず使われます。入力が有効な UTF-8 文字列と分かっているならば、いくつかのビットを理論的に決定することができます。
  • 平文: あらかじめ分かっている入力に対する出力が知られてしまうと、鍵には脆弱性が生じます。
  • ブルートフォース: 鍵や secret や seed を攻撃します。

PHP でのデコード方法

PHP スクリプトが LSL Wiki にあります。 古いバージョンのコードがここにあります: llXorBase64StringsCorrect in PHP

Java でのデコード方法

GET メソッドで送信する際は、必ず BASE64 ハッシュを URLEncode しましょう...

       String BASE64datahash = "error";
       String passhash = "error";

       try {
        //URL エンコードされた暗号化済みデータを URLDecode します。
        BASE64datahash = java.net.URLDecoder.decode("KhoFRRYaAUMbEVU%3D", "UTF-8"); //KhoFRRYaAUMbEVU%3D
        System.out.println("BASE64datahash: " + BASE64datahash); //KhoFRRYaAUMbEVU=

        //任意の BASE64 データの配列を作成します。
        char[] BASE64data = BASE64datahash.toCharArray();
        char[] dataUB = new String(new BASE64Decoder().decodeBuffer(new String(BASE64data))).toCharArray(); //データを BASE64 デコードします。
        System.out.println("encrypted data (but base64 decoded) [dataUB]: " + new String(dataUB));


        //秘密鍵・パスワードを BASE64 にエンコードします (BASE64Encoder の使い方を示すためだけのものです)
        //String BASE64password = new String(new BASE64Encoder().encodeBuffer("supersecretpassword".getBytes()));
        //System.out.println("BASE64password: " + new String(BASE64password));

        //BASE64 キー・パスワードの配列を作成します。
        //char[] key = BASE64password.toCharArray();
        //char[] keyUB = new String(new BASE64Decoder().decodeBuffer(new String(key))).toCharArray();
        char[] keyUB = "supersecretpassword".toCharArray(); 
        System.out.println("plaintext key/password [keyUB]: " + new String(keyUB));

        //データ配列を、対応するキー・パスワードの配列と 1 文字 1 文字 XOR していきます。
        int k=0;
        for (int i = 0; i < dataUB.length; i++) {
            dataUB[i] = (char) (dataUB[i] ^ keyUB[k]);
            k++;

            //キーが短すぎる場合はキーを繰り返します。
            if (k == keyUB.length)
               k=0;
		}

        System.out.println("Decoded data [dataUB]: " + new String(dataUB));
        
        } catch (Exception ex) {
            System.out.println("Oops!");
        }

特記事項

All Issues

~ Search JIRA for related Issues
   llXorBase64StringsCorrect zero out last (bitcount % 8) bits of data.

Signature

function string llXorBase64StringsCorrect( string str1, string str2 );
この翻訳は 原文 と比べて古いですか?間違いがありますか?読みにくいですか?みんなで 修正 していきましょう! (手順はこちら)
この項目はあなたにとって参考にならない項目ですか?もしかしたらLSL Wikiの関連した項目が参考になるかもしれません。