View Javadoc
1   /*
2    * License : The MIT License
3    * Copyright(c) 2022 Olyutorskii
4    */
5   
6   package io.github.olyutorskii.aletojio.bijection;
7   
8   import io.github.olyutorskii.aletojio.rng.RndInt32;
9   import java.util.Arrays;
10  import java.util.Objects;
11  
12  /**
13   * P-box diffusion by bit permutation.
14   *
15   * <p>Takes a 32-bit integer as input and outputs a diffused 32-bit integer.
16   *
17   * @see <a href="https://en.wikipedia.org/wiki/Permutation_box">
18   * Permutation box (Wikipedia)
19   * </a>
20   * @see <a href="https://en.wikipedia.org/wiki/Confusion_and_diffusion">
21   * Confusion_and_diffusion (Wikipedia)
22   * </a>
23   * @see <a href="https://en.wikipedia.org/wiki/Substitution%E2%80%93permutation_network">
24   * Substitution-permutation network (SPN) (Wikipedia)
25   * </a>
26   */
27  public class Pbox32 implements RndInt32 {
28  
29      private static final String ERRMSG_LENGTH = "P-box table must be 32 entry";
30      private static final String ERRMSG_BIJECTION = "P-box table must be bijection";
31  
32      private static final int START = 17;
33      private static final int STEP = 19;
34  
35      private static final int[] DEF_PERM;
36  
37      static {
38          DEF_PERM = new int[Integer.SIZE];
39          for (int ct = 0; ct < Integer.SIZE; ct++) {
40              DEF_PERM[ct] = (START + STEP * ct) % Integer.SIZE;
41          }
42      }
43  
44  
45      private final RndInt32 rnd;
46      private final int[] permute = new int[Integer.SIZE];
47  
48  
49      /**
50       * Constructor.
51       *
52       * <p>Default P-box tabel is used. {@code p[N] = (17 + 19 * N) mod 32}
53       *
54       * @param rndArg random source
55       */
56      public Pbox32(RndInt32 rndArg)
57              throws NullPointerException, IllegalArgumentException {
58          this(rndArg, DEF_PERM);
59          return;
60      }
61  
62      /**
63       * Constructor.
64       *
65       * <p>P-box table length must be 32.
66       *
67       * <p>P-box table must be bijection. (minimal perfect hash function)
68       *
69       * <p>{@code (permuteArg[31] = 7)} means copying bit from bit-31 to bit-7.
70       *
71       * @param rndArg random source
72       * @param permuteArg P-box bit-permutation table
73       * @throws NullPointerException null argument
74       * @throws IllegalArgumentException invalid P-box
75       */
76      public Pbox32(RndInt32 rndArg, int[] permuteArg)
77              throws NullPointerException, IllegalArgumentException {
78          super();
79          Objects.requireNonNull(rndArg);
80          Objects.requireNonNull(permuteArg);
81  
82          this.rnd = rndArg;
83  
84          checkPbox(permuteArg);
85          System.arraycopy(permuteArg, 0, this.permute, 0, Integer.SIZE);
86  
87          return;
88      }
89  
90  
91      /**
92       * Map int value with default P-box table.
93       *
94       * <p>Default P-box tabel is used. {@code p[N] = (17 + 19 * N) mod 32}
95       *
96       * @param iVal int value
97       * @return mapped value
98       */
99      public static int mapPermutation(int iVal) {
100         int result = mapTable(iVal, DEF_PERM);
101         return result;
102     }
103 
104     /**
105      * Map int value with specified P-box table.
106      *
107      * <p>There is no bijection check.
108      *
109      * @param iVal int value
110      * @param table P-box table
111      * @return mapped value
112      * @throws NullPointerException table is null
113      */
114     public static int mapTable(int iVal, int[] table) {
115         Objects.requireNonNull(table);
116 
117         int result = 0;
118 
119         for (int idx = 0; idx < Integer.SIZE; idx++) {
120             int bitVal = (iVal >>> idx) & 0b1;
121             int toPos = table[idx];
122             result |= bitVal << toPos;
123         }
124 
125         return result;
126     }
127 
128     /**
129      * Check P-box table.
130      *
131      * <p>P-box table length must be 32.
132      *
133      * <p>P-box table must be bijection. (minimal perfect hash function)
134      *
135      * <p>{@code (permuteArg[31] = 7)} means copying bit from bit-31 to bit-7.
136      *
137      * @param permuteArg P-box table
138      * @throws NullPointerException null argument
139      * @throws IllegalArgumentException size unmatch or not bijection detected
140      */
141     public static void checkPbox(int[] permuteArg)
142             throws NullPointerException, IllegalArgumentException {
143         Objects.requireNonNull(permuteArg);
144         if (permuteArg.length != Integer.SIZE) {
145             throw new IllegalArgumentException(ERRMSG_LENGTH);
146         }
147 
148         // checking minimal perfect hash function or not
149         int[] sorted = Arrays.copyOf(permuteArg, Integer.SIZE);
150         Arrays.sort(sorted);
151         for (int src = 0; src < Integer.SIZE; src++) {
152             int dst = sorted[src];
153             if (dst != src) {
154                 throw new IllegalArgumentException(ERRMSG_BIJECTION);
155             }
156         }
157 
158         return;
159     }
160 
161 
162     /**
163      * {@inheritDoc}
164      *
165      * @return {@inheritDoc}
166      */
167     @Override
168     public int nextInt32() {
169         int iVal = this.rnd.nextInt32();
170         int result = mapTable(iVal, this.permute);
171         return result;
172     }
173 
174 }