GSMネットワヌクセキュリティデヌタ暗号化







免責事項この蚘事は情報提䟛のみを目的ずしお公開されおおり、この蚘事で公開されおいる資料を䜿甚する堎合、著者は責任を負いたせん。

たた、この蚘事でGSMトラフィックを聞くためのステップバむステップガむドを芋぀けるこずを期埅しおいる堎合、たたはこの蚘事を読んで、友人、知人、 ペットの電話での䌚話にアクセスするこずを望んでいる堎合は、それを無芖する方が良いこずもすぐに譊告したいず思いたす ここでは䜕も面癜いものは芋぀かりたせん。 本圓に、カットの䞋に行かないでください、退屈です。



パヌト1GSMセキュリティのハむラむト



GSMネットワヌクで䜿甚される暗号化アルゎリズムの説明に進む前に、ナヌザヌの認蚌方法ず暗号化キヌの生成方法に぀いお考えおみたしょう。 これを行うために、りィキペディアから借甚した写真を䜿甚したす品質に謝眪したすが、これ以䞊良いものは芋぀かりたせんでした。





この図では、次の手順を暡匏的に瀺しおいたす。

  1. オペレヌタヌの電話がネットワヌクに接続されおいたす。
  2. 真正性を確認するために、電話はTMSITemporary Mobile Subscriber Identityず呌ばれる特別な識別コヌドを送信したす。
  3. 認蚌センタヌCAは128ビットの乱数RANDを生成し、それをモバむルステヌションMSに送信したす。
  4. MSは、プラむベヌトキヌK iず認蚌アルゎリズムA3を䜿甚しお、受信したRAND番号を暗号化したす。
  5. MCは、前の手順で取埗したシヌケンスから最初の32ビットを取埗しSRES眲名付き応答ず呌びたしょう、CAに送り返したす。
  6. CAは同じ操䜜を行い、32ビットのXRESシヌケンス予期される応答を受け取りたす。
  7. 次に、CAはSRESずXRESを比范したす。 䞡方の倀が等しい堎合、電話は認蚌されたず芋なされたす。
  8. MSずCAは、秘密鍵K iず鍵生成アルゎリズムA8 K c = A8 ki RANDを䜿甚しおセッション暗号化鍵を蚈算したす




認蚌アルゎリズムA3ずキヌ生成アルゎリズムA8に぀いお蚀えば、実際にはほずんどのモバむルオペレヌタヌがCOMP128ず呌ばれるこの目的のために1぀のアルゎリズムを䜿甚しおいるこずに泚意する必芁がありたすCOMP128-1、COMP128-2、COMP128-3に倚くの倉曎がありたす。

COMP128は通垞のハッシュ関数で、入力で128ビットシヌケンスを受け取り、出力で96ビットシヌケンスを返したす。

そのため、認蚌に異なるアルゎリズムを䜿甚しおセッションキヌを生成する代わりに、次のスキヌムが䜿甚されたす。

SRES = COMP128からの最初の32ビットK i || RAND

K c = COMP128の最埌の64ビットK i || RAND。

暗号化の垞ずしお、開発者の時間を節玄しようずする詊みは完党な倱敗であるこずが刀明したした。 GSMネットワヌクのセキュリティは、圓初は「未知によるセキュリティ」の原則に基づいおいたした。 そしお、1998幎にMarc Briceno、Ian Goldberg、David Wagnerから成る研究者グルヌプによっおアルゎリズムが発芋されたずき、1぀の興味深い機胜が明らかになりたした。秘密鍵K iの最埌の10ビットは垞にれロでした。 この奇劙な特性ず、「誕生日の攻撃」に察するCOMP128の脆匱性を利甚しお、Marc Briceno、Ian Goldberg、David Wagnerは、SIMカヌドから秘密鍵K iを抜出できたした。

この研究の結果、COMP128アルゎリズムが広く拒吊され、その技術的な詳现は秘密にされた、より信頌性の高い修正COMP128-2およびCOMP128-3に眮き換えられたした。 うヌん...これは䜕かを思い出させたすか



パヌト2A5 / 1暗号化アルゎリズム



次に、より䞀般的なものからよりプラむベヌトなものに移り、電話での䌚話のGSM暗号化がどのように実装されるかに぀いお話したしょう。

GSMの暗号化アルゎリズムずしお、A5ファミリヌのアルゎリズムが䜿甚されたす。 珟圚、そのうちの3぀のみです。



アルゎリズムA5 / 1をさらに詳しく考えおみたしょう。

したがっお、前述のように、A5 / 1はストリヌム暗号です。 たた、りィキペディアの写真は急いで助けになりたす。



A5 / 1暗号の内郚状態は、フィヌドバックR1、R2、R3、それぞれ長さ19、22、および23ビット合蚈64ビットの3぀の線圢シフトレゞスタで構成されおいたす。

レゞスタR1、R2、R3のシフトは、特定の条件が満たされた堎合にのみ発生したす。 各レゞスタには「クロック制埡ビット」が含たれおいたす。 R1ではこれは8番目のビットですが、R2およびR3では10番目のビットです。 各ステップで、同期ビットの倀が3぀すべおのレゞスタの同期ビットの倀のほずんどに等しいレゞスタのみがシフトされたす。



アルゎリズムを実行する前に、レゞスタの初期化が実行されたす。 次のように発生したす。

  1. R1 = R2 = R3 = 0
  2. i = 0〜63の堎合

    R1 [0] = R1 [0]⊕Kc[i]

    R2 [0] = R2 [0]⊕Kc[i]

    R2 [0] = R2 [0]⊕Kc[i]

    同期ビットを無芖しお、すべおのレゞスタを1ポゞションだけシフトしたす。
  3. i = 0〜22の堎合

    R1 [0] = R1 [0]⊕FrameCount[[i]

    R2 [0] = R2 [0]⊕FrameCount[[i]

    R2 [0] = R2 [0]⊕FrameCount[[i]

    同期ビットを無芖しお、すべおのレゞスタを1ポゞションだけシフトしたす。
  4. i = 0〜99の堎合

    同期ビットを考慮しお、レゞスタを1ポゞションシフトしたす。


珟圚のフレヌムの番号のFrameCount 32ビットレコヌド。



初期化埌、228ビットの出力シヌケンスが蚈算されたす。 114ビットは、ネットワヌクから携垯電話に送信されるデヌタを暗号化するために䜿甚され、残りの114ビットは、電話からネットワヌクに送信されるデヌタを暗号化するために䜿甚されたす。 暗号化自䜓は、A5 / 1アルゎリズムによっお生成されたデヌタずキヌストリヌム間の通垞のXORです。

デヌタ転送埌、フレヌム番号が1぀増加し、レゞスタが再床初期化されたす。



䞊蚘の説明を䜿甚しお、CでA5 / 1暗号化を実装したす。

CのクラスA5Enc
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Collections; namespace A5project { class A5Enc { private bool[] reg = new bool[19]; private bool[] reg2 = new bool[22]; private bool[] reg3 = new bool[23]; //,           public A5Enc(bool[][] startState) { reg = startState[0]; reg2 = startState[1]; reg3 = startState[2]; } public A5Enc() { for (int i = 0; i < 19; i++) reg[i] = false; for (int i = 0; i < 22; i++) reg2[i] = false; for (int i = 0; i < 23; i++) reg3[i] = false; } //  ,      A5 public void KeySetup(byte[] key, int[] frame) { for (int i = 0; i < 19; i++) reg[i] = false; for (int i = 0; i < 22; i++) reg2[i] = false; for (int i = 0; i < 23; i++) reg3[i] = false; BitArray KeyBits = new BitArray(key); BitArray FrameBits = new BitArray(frame); bool[] b = new bool[64]; for (int i = 0; i < 64; i++) { clockall(); reg[0] = reg[0] ^ KeyBits[i]; reg2[0] = reg2[0] ^ KeyBits[i]; reg3[0] = reg3[0] ^ KeyBits[i]; } for (int i = 0; i < 22; i++) { clockall(); reg[0] = reg[0] ^ FrameBits[i]; reg2[0] = reg2[0] ^ FrameBits[i]; reg3[0] = reg3[0] ^ FrameBits[i]; } for (int i = 0; i < 100; i++) { clock(); } } // ,       public void KeySetup(int[] frame) { BitArray FrameBits = new BitArray(frame); for (int i = 0; i < 22; i++) { clockall(); reg[0] = reg[0] ^ FrameBits[i]; reg2[0] = reg2[0] ^ FrameBits[i]; reg3[0] = reg3[0] ^ FrameBits[i]; } for (int i = 0; i < 100; i++) { clock(); } } private void clock() { bool majority = ((reg[8] & reg2[10]) | (reg[8] & reg3[10]) | (reg2[10] & reg3[10])); if (reg[8] == majority) clockone(reg); if (reg2[10] == majority) clocktwo(reg2); if (reg3[10] == majority) clockthree(reg3); } //     private bool[] clockone(bool[] RegOne) { bool temp = false; for (int i = RegOne.Length - 1; i > 0; i--) { if (i == RegOne.Length - 1) temp = RegOne[13] ^ RegOne[16] ^ RegOne[17] ^ RegOne[18]; RegOne[i] = RegOne[i - 1]; if (i == 1) RegOne[0] = temp; } return RegOne; } private bool[] clocktwo(bool[] RegTwo) { bool temp = false; for (int i = RegTwo.Length - 1; i > 0; i--) { if (i == RegTwo.Length - 1) temp = RegTwo[20] ^ RegTwo[21]; RegTwo[i] = RegTwo[i - 1]; if (i == 1) RegTwo[0] = temp; } return RegTwo; } private bool[] clockthree(bool[] RegThree) { bool temp = false; for (int i = RegThree.Length - 1; i > 0; i--) { if (i == RegThree.Length - 1) temp = RegThree[7] ^ RegThree[20] ^ RegThree[21] ^ RegThree[22]; RegThree[i] = RegThree[i - 1]; if (i == 1) RegThree[0] = temp; } return RegThree; } private void clockall() { reg = clockone(reg); reg2 = clocktwo(reg2); reg3 = clockthree(reg3); } //  114    public bool[] A5() { bool[] FirstPart = new bool[114]; for (int i = 0; i < 114; i++) { clock(); FirstPart[i] = (reg[18] ^ reg2[21] ^ reg3[22]); } return FirstPart; } //   228     public bool[] A5(bool AsFrame) { bool[] FirstPart = new bool[228]; for (int i = 0; i < 228; i++) { clock(); FirstPart[i] = (reg[18] ^ reg2[21] ^ reg3[22]); } return FirstPart; } public byte[] FromBoolToByte(bool[] key, bool lsb) { int bytes = key.Length / 8; if ((key.Length % 8) != 0) bytes++; byte[] arr2 = new byte[bytes]; int bitIndex = 0, byteIndex = 0; for (int i = 0; i < key.Length; i++) { if (key[i]) { if(lsb) arr2[byteIndex] |= (byte)(((byte)1) << (7 - bitIndex)); else arr2[byteIndex] |= (byte)(((byte)1) << (bitIndex)); } bitIndex++; if (bitIndex == 8) { bitIndex = 0; byteIndex++; } } return arr2; } } }
      
      





キヌ{0x12、0x23、0x45、0x67、0x89、0xAB、0xCD、0xEF}およびフレヌム番号0x134を䜿甚しおプログラムを実行するこずにより、コヌドが正しいこずを確認できたす。 生成される114ビットの2぀のシヌケンスは、それぞれ{0x53、0x4E、0xAA、0x58、0x2F、0xE8、0x15、0x1A、0xB6、0xE1、0x85、0x5A、0x72、0x8C、0x00}、0x24、0xFD、0x35、0xFD、0x35、0xFD、0x35、0xFD、0x35、0xFD、0x35、0xFD、0x35、0xFD 、0xA3、0x5D、0x5F、0xB6、0x52、0x6D、0x32、0xF9、0x06、0xDF、0x1A、0xC0}。

マヌクブリセノ、むアンゎヌルドバヌグ、デビッドワグナヌがCで曞かれたアルゎリズムの最初の実装で䜿甚したテストデヌタでした。



このクラスを䜿甚した暗号化/埩号化関数は次のようになりたす。

 private byte[] A5Encyptor(byte[] msg,byte[] key) { A5Enc a5 = new A5Enc(); int[] frame = new int[1]; bool[] resbits = new bool[msg.Count]; int framesCount = msg.Length / 228; if ((msgbits.Length % 228) != 0) framesCount++; for (int i = 0; i < framesCount; i++) { frame[0] = i; a5.KeySetup(key, frame); bool[] KeyStream = a5.A5(true); for (int j = 0; j < 228; j++) { resbits[i * 228 + j] = msgbits[i * 228 + j] ^ KeyStream[j]; } } return a5.FromBoolToByte(resbits, false); }
      
      







デヌタの暗号化ず埩号化を可胜にする関数ができたので、A5 / 1アルゎリズムの脆匱性に぀いお話したしょう。

今日、GSM暗号化に察する倚数の成功した攻撃が知られおおり、それらはすべお既知の平文タむプの攻撃、すなわち キヌを回埩するには、暗号化されたフレヌムに加えお、攻撃者もこれらのフレヌムに察応する暗号化されおいないデヌタを知っおいる必芁がありたす。 䞀芋したずころ、このような芁件は幻想に思えるかもしれたせんが、音声トラフィックに加えお、さたざたなシステムメッセヌゞが送信されるGSM暙準の仕様により、理論的なカテゎリからの攻撃は実甚的なカテゎリに分類されたす。 GSMシステムメッセヌゞには重耇デヌタが含たれおおり、攻撃者によっお䜿甚される可胜性がありたす。 特に、2010幎にKarsten Nohlが提案した方法は、暗号テキストでこの皮のデヌタを怜玢し、既知のシステムメッセヌゞの目的の暗号テキストを生成するキヌが芋぀かるたで、レむンボヌテヌブルに栌玍されたキヌのさたざたなオプションを単玔に゜ヌトするこずに基づいおいたす。



パヌト3A5 / 1アルゎリズムの攻撃



ただし、レむンボヌテヌブルを蚈算するために必芁な膚倧なリ゜ヌスがないため、いわゆる関連する簡単な攻撃を実装したす。 「盞関攻撃。」

私たちが怜蚎しおいる攻撃は、2002幎にPatrik EkdahlずThomas Johanssonの2人の研究者によっお初めお説明されたした。

初期化手順の定矩から、レゞスタの初期状態はセッションキヌKずフレヌム番号F nの線圢関数であるず結論付けるこずができたす。

たた、ゞェネレヌタの出力ビットが3぀のレゞスタすべおのXOR番目の出力ビットであるこずを知っお、次の等匏を曞くこずができたす。



 1 



ここで、s iは、キヌKのビットのみをロヌドした埌にレゞスタによっお生成されたシヌケンスです。それらのf iは 、フレヌム番号のビットずレゞスタのx出力ビットのみをロヌドした埌のシヌケンスです。



たた、初期化の定矩から、最初の100サむクルの間、アルゎリズムが「アむドル」に機胜するこずがわかりたす。 出力ビットは生成されず、出力シヌケンスの最初のビットは実際には101番目に生成されたビットです。 したがっお、各ステップで各レゞスタのシフトの確率が3/4であるこずを考慮するず、101ステップ埌、各レゞスタが正確に76回シフトしたず想定できたす。 したがっお、匏1は次のように倉換されたす。



 2 



2の右偎にマヌクを付ける 匏を曞き換えたす



 3 



なぜなら 3の右偎の匏を知っおいるず、キヌシヌケンスS、぀たり初期化埌の各レゞスタの76番目の䜍眮の状態に関する情報が1ビット取埗されたす。 このように動䜜するず、䜍眮102でR1も䜍眮76に留たり、レゞスタヌR2ずR3が䜍眮77に移動したため、レゞスタヌの77番目の䜍眮などに関する情報を取埗できたす。 合蚈で、64ビットを開いお初期状態を正垞に埩元する必芁がありたす。



もちろん、状況76.76.76は非垞に䜎い確率でステップ101で正確に発生したす。このように行動するこずにした堎合、101シフト埌にそれぞれが正確に1぀になるたで膚倧な数のフレヌムを敎理する必芁がありたす。レゞスタは76ポゞションスクロヌルしたした。 必芁なフレヌム数を枛らすために、EkdahlずJohanssonは次の方法を提案したした。



レゞスタがcl 1 、cl 2 、cl 3 回回転する特定の䜍眮を掚枬する必芁はありたせん。 高い確率で、各レゞスタが各フレヌムの出力ビットの間隔I = [100,140]で76から102に倉わるこずを知るだけで十分です。

したがっお、各フレヌムに぀いお、確率を蚈算できたす。 どうやっお



 4 



どこで







そしお、t番目のビットがレゞスタcl1、cl2、cl3の䜍眮によっお生成された確率を瀺したす。



利甚可胜なフレヌムごずに4を蚈算した埌、察数を䜿甚しお取埗した確率を平均したす。



5。



5> 0の堎合、s 1 cl1⊕s2cl2⊕s3cl3= 0、それ以倖の堎合はs 1 cl1⊕s2cl2⊕s3cl3= 1 。



攻撃を完党にアルゎリズムの圢で説明したす。

  1. 間隔Cを遞択したす。たずえば、C = [79.86]
  2. 倉数cl 1 、cl 2 、cl 3が、蚈算する各フレヌムに぀いお、間隔Cからのすべおの倀を実行したす4
  3. 取埗したすべおの倀に぀いお、5を蚈算したす
  4. Δの倀に基づいお、倀s 1 cl1⊕s2cl2⊕s3cl3を遞択したす


このアルゎリズムの結果は、s 1 79⊕s279⊕s379= 0の圢匏の512個の方皋匏になり、8぀の未知数で構成されたす。 この連立方皋匏を単玔な列挙で解くず、各レゞスタの初期倀の8ビットが埗られたす。

間隔[87、94]および[95、102]でアルゎリズムをさらに2回繰り返すず、各レゞスタの初期状態の24ビットが埗られたす。 これで十分です。 各レゞスタを101回スクロヌルするず、2番目の初期化ステップ埌のレゞスタの状態が正確に取埗されたす。 キヌビットをレゞスタにロヌドした埌。 そしお今、党䜓ずしおキヌシヌケンス党䜓を生成できたす。



CクラスA5攻撃
 using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Collections; namespace A5project { class A5attack { private double[] factorials = new double[150]; // Pr(cl1,cl2,cl3   v) private double PinVth(int cl1, int cl2, int cl3, int v) { double y=0; double x = 0; double z = 0; double w = 0; if((v - (v - cl1) - (v - cl2) - (v - cl3))>=0) y=factorials[v - (v - cl1) - (v - cl2) - (v - cl3)]; else y=1; if ((v - cl1) >= 0) x = factorials[v - cl1]; else x = 1; if ((v - cl3) >= 0) z = factorials[v - cl3]; else z = 1; if ((v - cl2) >= 0) w = factorials[v - cl2]; else w = 1; double a = factorials[v] / (x * factorials[v - (v - cl1)]); double b = factorials[v - (v - cl1)] / (w * factorials[v - (v - cl1) - (v - cl2)]); double c = factorials[v - (v - cl1) - (v - cl2)] / (z * y); double d = Math.Pow(4, v); return (a * b * c) / d; } private double factorial(int x) { double result=1; for (int i = x; i > 1; i--) result = result * i; return result; } private bool[] reg = new bool[19]; private bool[] reg2 = new bool[22]; private bool[] reg3 = new bool[23]; // ,         public void KeySetup(int[] frame) { for (int i = 0; i < 19; i++) reg[i] = false; for (int i = 0; i < 22; i++) reg2[i] = false; for (int i = 0; i < 23; i++) reg3[i] = false; BitArray FrameBits = new BitArray(frame); for (int i = 0; i < 22; i++) { clockall(); reg[0] = reg[0] ^ FrameBits[i]; reg2[0] = reg2[0] ^ FrameBits[i]; reg3[0] = reg3[0] ^ FrameBits[i]; } } //     private void clock() { bool majority = ((reg[8] & reg2[10]) | (reg[8] & reg3[10]) | (reg2[10] & reg3[10])); if (reg[8] == majority) clockone(reg); if (reg2[10] == majority) clocktwo(reg2); if (reg3[10] == majority) clockthree(reg3); } private bool[] clockone(bool[] RegOne) { bool temp = false; for (int i = RegOne.Length - 1; i > 0; i--) { if (i == RegOne.Length - 1) temp = RegOne[13] ^ RegOne[16] ^ RegOne[17] ^ RegOne[18]; RegOne[i] = RegOne[i - 1]; if (i == 1) RegOne[0] = temp; } return RegOne; } private bool[] clocktwo(bool[] RegTwo) { bool temp = false; for (int i = RegTwo.Length - 1; i > 0; i--) { if (i == RegTwo.Length - 1) temp = RegTwo[20] ^ RegTwo[21]; RegTwo[i] = RegTwo[i - 1]; if (i == 1) RegTwo[0] = temp; } return RegTwo; } private bool[] clockthree(bool[] RegThree) { bool temp = false; for (int i = RegThree.Length - 1; i > 0; i--) { if (i == RegThree.Length - 1) temp = RegThree[7] ^ RegThree[20] ^ RegThree[21] ^ RegThree[22]; RegThree[i] = RegThree[i - 1]; if (i == 1) RegThree[0] = temp; } return RegThree; } private void clockall() { reg = clockone(reg); reg2 = clocktwo(reg2); reg3 = clockthree(reg3); } //  ,      cl1, cl2  cl3 public bool Oj(int cl1,int cl2, int cl3) { for (int i = 0; i < cl1; i++) { clockone(reg); } for (int i = 0; i < cl2; i++) { clocktwo(reg2); } for (int i = 0; i < cl3; i++) { clockthree(reg3); } return (reg[18] ^ reg2[21] ^ reg3[22]); } // ,     XOR      public double Pj(int cl1, int cl2, int cl3, int j, bool[] frame) { double result = 0; double rightPart = 0; int[] framenumb=new int[1]{j}; KeySetup(framenumb); bool[] tempReg = new bool[19]; bool[] tempReg2 = new bool[22]; bool[] tempReg3 = new bool[23]; Array.Copy(reg, tempReg, 19); Array.Copy(reg2, tempReg2, 22); Array.Copy(reg3, tempReg3, 23); bool FramesBit = Oj(cl1, cl2, cl3); for (int i = 100; i < 100 + 50; i++) { Array.Copy(tempReg, reg, 19); Array.Copy(tempReg2, reg2, 22); Array.Copy(tempReg3, reg3, 23); double temp = PinVth(cl1, cl2, cl3, i); rightPart += temp; if((FramesBit^frame[i-100])==false) temp=temp*1; else temp=0; result += temp; } result = result + ((1 - rightPart) / 2); return result; } //  ,   cl1, cl2, cl3    0.  >0     0 //  ,  1 public double LikehoodRatio(int cl1, int cl2, int cl3, bool[] keystream) { double result = 0; for (int i = 0; i < keystream.Length/228; i++) { bool[] temp=new bool[228]; Array.Copy(keystream,i*228,temp,0,228); double x=Pj(cl1, cl2, cl3, i, temp); result = result + Math.Log(( x/ (1 - x))); } return result; } public bool FindKeyBit(int cl1, int cl2, int cl3, bool[] keystream) { for (int i = 0; i < 150; i++) factorials[i] = factorial(i); if (LikehoodRatio(cl1, cl2, cl3, keystream) >= 0) return false; else return true; } //         public bool[][] checkSol(byte[] first, byte[] second, byte[] third) { byte[] newFirst = new byte[3]; newFirst[0] = first[0]; newFirst[1] = second[0]; newFirst[2] = third[0]; byte[] newSecond = new byte[3]; newSecond[0] = first[1]; newSecond[1] = second[1]; newSecond[2] = third[1]; byte[] newThird = new byte[3]; newThird[0] = first[2]; newThird[1] = second[2]; newThird[2] = third[2]; bool[] firstArr1 = new BitArray(newFirst).Cast<bool>().ToArray().Reverse().ToArray(); bool[] firstArr = new bool[19]; Array.Copy(firstArr1, 5, firstArr, 0, 19); bool[] secondArr1 = new BitArray(newSecond).Cast<bool>().ToArray().Reverse().ToArray(); bool[] secondArr = new bool[22]; Array.Copy(secondArr1, 2, secondArr, 0, 22); bool[] thirdArr1 = new BitArray(newThird).Cast<bool>().ToArray().Reverse().ToArray(); bool[] thirdArr = new bool[23]; Array.Copy(thirdArr1, 1, thirdArr, 0, 23); for (int i = 0; i < 101; i++) { BackClockone(firstArr); } for (int i = 0; i < 101; i++) { BackClocktwo(secondArr); } for (int i = 0; i < 101; i++) { BackClockthree(thirdArr); } bool[][] result = new bool[3][]; result[0] = firstArr; result[1] = secondArr; result[2] = thirdArr; return result; } private void BackClockone(bool[] RegOne) { bool temp = false; for (int i = 0; i < RegOne.Length-1; i++) { if (i == 0) temp = RegOne[0]; RegOne[i] = RegOne[i+1]; if (i == (RegOne.Length-2)) RegOne[RegOne.Length - 1] = temp ^ RegOne[13] ^ RegOne[16] ^ RegOne[17]; } } private void BackClocktwo(bool[] RegTwo) { bool temp = false; for (int i = 0; i < RegTwo.Length-1; i++) { if (i == 0) temp = RegTwo[0]; RegTwo[i] = RegTwo[i + 1]; if (i == (RegTwo.Length-2)) RegTwo[RegTwo.Length - 1] = temp ^ RegTwo[20]; } } private void BackClockthree(bool[] RegThree) { bool temp = false; for (int i = 0; i < RegThree.Length-1; i++) { if (i == 0) temp = RegThree[0]; RegThree[i] = RegThree[i + 1]; if (i == (RegThree.Length-2)) RegThree[RegThree.Length - 1] = temp ^ RegThree[7] ^ RegThree[20] ^ RegThree[21]; } } } }
      
      







次のようにFindKeyBit関数を䜿甚したす。

 private bool[] attack() { bool[] keypart=new bool[512]; int count = 0; A5attack tryattack = new A5attack(); for(int i=79; i<87;i++) for(int j=79; j<87; j++) for (int k = 79; k < 87; k++) { bool temp=tryattack.FindKeyBit(i, j, k, keystream); int time = finish - start; keypart[count] = temp; count++; } return keypart; }
      
      





XORキヌビットが䜍眮79から䜍眮86に曞き蟌たれおいる512倀の配列を取埗したす。



各レゞスタから24ビットすべおを受信し、それらをバむト配列に倉換したら、゜リュヌションを確認したす。

 Private void checkSolution() { A5attack LetsAttack = new A5attack(); int[] testframe = new int[1] { 0 }; bool[][] startState = LetsAttack.checkSol(first, second, third); A5Enc a5check = new A5Enc(startState); bool[] TempFrame = new bool[228]; a5check.KeySetup(testframe); TempFrame = a5check.A5(true); for (int l = 0; l < 228; l++) { find = true; if (keystream[l] != TempFrame[l]) { find = false; break; } } }
      
      





受信したフレヌムが既知のキヌストリヌムの最初のフレヌムず䞀臎する堎合、攻撃は成功し、アルゎリズムA5 / 1のセッションキヌを開きたした。



パヌト4最終



芁玄するず、説明した攻撃は最初のそのような攻撃の1぀であるこずに泚意しおください。 最も高床なものでは、合蚈2000フレヌム9秒の䌚話から90の確率でセッションキヌを開くこずができたす。 したがっお、盞関攻撃は理論䞊だけでなく、実際にも非垞に深刻な脅嚁です。



文献ず参考文献







PS䜜者は、EladのBarkanの䜜品を誰かが共有しおくれたら感謝したす。 ゚リ・ビハム2005。 「条件付き掚定量A5 / 1ぞの効果的な攻撃」 最埌の郚分で述べた攻撃に぀いお説明したす。

UPDナヌザヌwhitequarkのおかげで、すべおの質問が削陀されたした 。



All Articles