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      // N.B. 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       * <p>
73       * The salt is generated with {@link SecureRandom}.
74       * </p>
75       *
76       * @param num Number of chars to generate.
77       * @return a random salt {@link String}.
78       */
79      static String getRandomSalt(final int num) {
80          return getRandomSalt(num, new SecureRandom());
81      }
82  
83      /**
84       * Generates a string of random chars from the B64T set.
85       * <p>
86       * The salt is generated with the {@link Random} provided.
87       * </p>
88       *
89       * @param num Number of chars to generate.
90       * @param random an instance of {@link Random}.
91       * @return a random salt {@link String}.
92       */
93      static String getRandomSalt(final int num, final Random random) {
94        final StringBuilder saltString = new StringBuilder(num);
95        for (int i = 1; i <= num; i++) {
96          saltString.append(B64T_STRING.charAt(random.nextInt(B64T_STRING.length())));
97        }
98        return saltString.toString();
99      }
100 }