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    *      http://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();
42  
43      /**
44       * Base64 like conversion of bytes to ASCII chars.
45       *
46       * @param b2
47       *            A byte from the result.
48       * @param b1
49       *            A byte from the result.
50       * @param b0
51       *            A byte from the result.
52       * @param outLen
53       *            The number of expected output chars.
54       * @param buffer
55       *            Where the output chars is appended to.
56       */
57      static void b64from24bit(final byte b2, final byte b1, final byte b0, final int outLen,
58                               final StringBuilder buffer) {
59          // The bit masking is necessary because the JVM byte type is signed!
60          int w = b2 << 16 & 0x00ffffff | b1 << 8 & 0x00ffff | b0 & 0xff;
61          // It's effectively a "for" loop but kept to resemble the original C code.
62          int n = outLen;
63          while (n-- > 0) {
64              buffer.append(B64T_ARRAY[w & 0x3f]);
65              w >>= 6;
66          }
67      }
68  
69      /**
70       * Generates a string of random chars from the B64T set.
71       * <p>
72       * The salt is generated with {@link SecureRandom}.
73       * </p>
74       *
75       * @param num Number of chars to generate.
76       * @return a random salt {@link String}.
77       */
78      static String getRandomSalt(final int num) {
79          return getRandomSalt(num, new SecureRandom());
80      }
81  
82      /**
83       * Generates a string of random chars from the B64T set.
84       * <p>
85       * The salt is generated with the {@link Random} provided.
86       * </p>
87       *
88       * @param num Number of chars to generate.
89       * @param random an instance of {@link Random}.
90       * @return a random salt {@link String}.
91       */
92      static String getRandomSalt(final int num, final Random random) {
93        final StringBuilder saltString = new StringBuilder(num);
94        for (int i = 1; i <= num; i++) {
95          saltString.append(B64T_STRING.charAt(random.nextInt(B64T_STRING.length())));
96        }
97        return saltString.toString();
98      }
99  }