Encryption

如何製作一個好的加密器?

  • November 2, 2014

我正在使用自己的 PRNG 為流密碼製作加密器軟體,作為校際科學競賽的項目。我怎樣才能製作一個,以便在它生成偽隨機編號之後。它可以辨識每個字元並進行轉換。任何人都可以用 Python 或虛擬碼算法來解釋這一點。

我試著自己做一個,但我不確定它是否會起作用。它是這樣工作的:首先,程序開始計算並記錄我們輸入的每個字元,有點像鍵盤記錄器。它必須能夠唯一地辨識每個字元。然後它進行換檔。如果它足夠好,我可以按原樣使用它還是必須進行更改。

說你有價值 $ n $ 這是字母表的大小(即構成明文和密文的字元範圍)。並說 $ m = x \times n $ 是您擁有的不高於的最大值 $ y $ 在哪裡 $ y $ 是您的隨機數生成器產生的最大尺寸。

對於每個字元:

  1. 從隨機數生成器中取值,直到你的值小於 $ m $ , 呼叫這個值 $ r_i $ ;
  2. 計算 $ s_i $ 這很簡單 $ r_i \bmod n $ ;
  3. 計算 $ p_i $ 這是字母表中目前字元的位置;
  4. 計算 $ c_i = (p_i + s_i) \bmod n $
  5. 將角色帶到位置 $ c_i $ 的字母表和顯示。

扭轉:

  1. 從隨機數生成器中取值,直到你的值小於 $ m $ , 呼叫這個值 $ r_i $ ;
  2. 計算 $ s_i $ 這很簡單 $ r_i \bmod n $ ;
  3. 計算 $ c_i $ 這是字母表中目前字元的位置(字母表中的第一個字元位於位置 0);
  4. 計算 $ p_i = (c_i - s_i) \bmod n $
  5. 將角色帶到位置 $ p_i $ 的字母表和顯示。

在上述計算中,我假設隨機數生成器從 $ 0 $ 取決於 $ y $ (所以沒有 $ y $ )。這些字元在一個字母表中,它們有一個索引 $ 0 $ 取決於 $ n $ (所以沒有 $ n $ ).

如果 $ y = n $ (隨機數生成器的最大值與字母的大小相同)那麼方案當然更簡單。您可以只取隨機數生成器的下一個值並呼叫它 $ s_i $ ,跳過前兩個步驟。


Java 中的範例實現(抱歉,不太了解 Python):

import java.nio.charset.StandardCharsets;
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;

public class StreamCryptUsingAlphabet {

   private String alphabet;
   private int n;
   private int y;
   private int m;

   private SecureRandom rng;

   public StreamCryptUsingAlphabet(String alphabet, int y) {
       this.alphabet = alphabet;
       this.n = alphabet.length();
       if (y < n) {
           throw new IllegalArgumentException("y is too small");
       }

       this.y = y;
       // % is the remainder operator, same as modulus for positive numbers
       this.m = y - y % n;
   }

   public void init(byte[] seed) {
       try {
           rng = SecureRandom.getInstance("SHA1PRNG");
       } catch (NoSuchAlgorithmException e) {
           throw new IllegalStateException("RNG not available");
       }
       rng.setSeed(seed);
   }

   private int nextS() {
       int r;
       do {
           r = rng.nextInt(y);
       } while (r >= m);
       return r % n;
   }

   public String encrypt(String plaintext) {
       String ciphertext = "";
       for (int i = 0; i < plaintext.length(); i++) {
           int p = indexInAlphabet(plaintext.charAt(i));
           int s = nextS();
           int c = (p + s) % n;
           ciphertext += characterInAlphabet(c);
       }
       return ciphertext;
   }

   public String decrypt(String ciphertext) {
       String plaintext = "";
       for (int i = 0; i < ciphertext.length(); i++) {
           int c = indexInAlphabet(ciphertext.charAt(i));
           int s = nextS();
           // Java's remainder requires me to add n first
           int p = (c - s + n) % n;
           plaintext += characterInAlphabet(p);
       }
       return plaintext;
   }

   private int indexInAlphabet(char c) {
       String s = String.valueOf(c);
       return alphabet.indexOf(s);
   }

   private char characterInAlphabet(int i) {
       return alphabet.charAt(i);
   }

   public static void main(String[] args) {
       byte[] key = "Khan".getBytes(StandardCharsets.US_ASCII);

       StreamCryptUsingAlphabet sc = new StreamCryptUsingAlphabet(
               "abcdefghijklmnopqrstuvwxyz", 80);

       sc.init(key);
       String ct = sc.encrypt("owlstead");

       sc.init("Khan".getBytes(StandardCharsets.US_ASCII));
       String pt = sc.decrypt(ct);
       System.out.println(pt);
   }
}

下一部分解釋瞭如果密鑰流是偽隨機流通常會做什麼……

通常,如果您生成了隨機密鑰流,那麼我們使用 XOR 來加密純文字。為此,明文也需要是二進制的。所以如果明文實際上是文本,我們需要對其進行字元編碼。常用的編碼是 US ASCII 和 UTF-8。但是,這將產生二進制密文,因此如果要將其表示為字元串,則可以使用 base 64 編碼。

要解密您首先要對您收到的數據進行 base 64 解碼以檢索密文。然後解密,然後使用字元解碼從二進制明文中檢索文本。

所以上面是通常在電腦內完成的事情。

引用自:https://crypto.stackexchange.com/questions/19965