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 }