View Javadoc
1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one or more
3    * contributor license agreements.  See the NOTICE file distributed with
4    * this work for additional information regarding copyright ownership.
5    * The ASF licenses this file to You under the Apache License, Version 2.0
6    * (the "License"); you may not use this file except in compliance with
7    * the License.  You may obtain a copy of the License at
8    *
9    *      https://www.apache.org/licenses/LICENSE-2.0
10   *
11   * Unless required by applicable law or agreed to in writing, software
12   * distributed under the License is distributed on an "AS IS" BASIS,
13   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14   * See the License for the specific language governing permissions and
15   * limitations under the License.
16   */
17  package org.apache.commons.codec.digest;
18  
19  import java.security.SecureRandom;
20  import java.util.Random;
21  
22  /**
23   * Base64-like method to convert binary bytes into ASCII chars.
24   * <p>
25   * TODO: Can Base64 be reused?
26   * </p>
27   * <p>
28   * This class is immutable and thread-safe.
29   * </p>
30   */
31  final class B64 {
32  
33      /**
34       * Table with characters for Base64 transformation.
35       */
36      static final String B64T_STRING = "./0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
37  
38      /**
39       * Table with characters for Base64 transformation.
40       */
41      static final char[] B64T_ARRAY = B64T_STRING.toCharArray(); // package access for testing
42      // Do not make this protected or public. Array contents are mutable!
43  
44      /**
45       * Base64 like conversion of bytes to ASCII chars.
46       *
47       * @param b2
48       *            A byte from the result.
49       * @param b1
50       *            A byte from the result.
51       * @param b0
52       *            A byte from the result.
53       * @param outLen
54       *            The number of expected output chars.
55       * @param buffer
56       *            Where the output chars is appended to.
57       */
58      static void b64from24bit(final byte b2, final byte b1, final byte b0, final int outLen,
59                               final StringBuilder buffer) {
60          // The bit masking is necessary because the JVM byte type is signed!
61          int w = b2 << 16 & 0x00ffffff | b1 << 8 & 0x00ffff | b0 & 0xff;
62          // It's effectively a "for" loop but kept to resemble the original C code.
63          int n = outLen;
64          while (n-- > 0) {
65              buffer.append(B64T_ARRAY[w & 0x3f]);
66              w >>= 6;
67          }
68      }
69  
70      /**
71       * Generates a string of random chars from the B64T set.
72       *
73       * <p>
74       * The salt is generated with {@link SecureRandom}.
75       * </p>
76       *
77       * @param num Number of chars to generate.
78       * @return a random salt {@link String}.
79       */
80      static String getRandomSalt(final int num) {
81          return getRandomSalt(num, new SecureRandom());
82      }
83  
84      /**
85       * Generates a string of random chars from the B64T set.
86       *
87       * <p>
88       * The salt is generated with the {@link Random} provided.
89       * </p>
90       *
91       * @param num Number of chars to generate.
92       * @param random an instance of {@link Random}.
93       * @return a random salt {@link String}.
94       */
95      static String getRandomSalt(final int num, final Random random) {
96        final StringBuilder saltString = new StringBuilder(num);
97        for (int i = 1; i <= num; i++) {
98          saltString.append(B64T_STRING.charAt(random.nextInt(B64T_STRING.length())));
99        }
100       return saltString.toString();
101     }
102 }