Skip to content

Commit

Permalink
alibaba#10930 forward compatible old version secretKey
Browse files Browse the repository at this point in the history
  • Loading branch information
xyohn committed Aug 8, 2023
1 parent 03f2191 commit 445fb90
Show file tree
Hide file tree
Showing 3 changed files with 157 additions and 9 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -18,11 +18,10 @@

import com.alibaba.nacos.plugin.auth.exception.AccessException;
import com.alibaba.nacos.plugin.auth.impl.users.NacosUser;
import com.alibaba.nacos.plugin.auth.impl.utils.Base64Decode;

import javax.crypto.spec.SecretKeySpec;
import java.nio.charset.StandardCharsets;
import java.security.Key;
import java.util.Base64;
import java.util.concurrent.TimeUnit;

/**
Expand All @@ -39,13 +38,7 @@ public class NacosJwtParser {
private final Key key;

public NacosJwtParser(String base64edKey) {
byte[] decode;
try {
decode = Base64.getDecoder().decode(base64edKey);
} catch (IllegalArgumentException e) {
decode = base64edKey.getBytes(StandardCharsets.US_ASCII);
}

byte[] decode = Base64Decode.decode(base64edKey);
int bitLength = decode.length << 3;
if (bitLength < 256) {
String msg = "The specified key byte array is " + bitLength + " bits which "
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,126 @@
/*
* Copyright 1999-2022 Alibaba Group Holding Ltd.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package com.alibaba.nacos.plugin.auth.impl.utils;

import java.util.Arrays;

/**
* Base64Decoder.
*
* @author xYohn
* @date 2023/8/7
*/
public class Base64Decode {
private static final char[] BASE64_ALPHABET = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/".toCharArray();

private static final int[] BASE64_IALPHABET = new int[256];

private static final int IALPHABET_MAX_INDEX = BASE64_IALPHABET.length - 1;

private static final int[] IALPHABET = BASE64_IALPHABET;

static {
Arrays.fill(BASE64_IALPHABET, -1);
for (int i = 0, iS = BASE64_ALPHABET.length; i < iS; i++) {
BASE64_IALPHABET[BASE64_ALPHABET[i]] = i;
}
BASE64_IALPHABET['='] = 0;
}

/**
* Decodes a Base64 encoded String into a newly-allocated byte array using the Base64 encoding scheme.
*
* @param input the string to decode
* @return a byte array containing binary data
*/
public static byte[] decode(String input) {

// Check special case
if (input == null || input.equals("")) {
return new byte[0];
}
char[] sArr = input.toCharArray();
int sLen = sArr.length;
if (sLen == 0) {
return new byte[0];
}

int sIx = 0;
int eIx = sLen - 1; // Start and end index after trimming.

// Trim illegal chars from start
while (sIx < eIx && IALPHABET[sArr[sIx]] < 0) {
sIx++;
}

// Trim illegal chars from end
while (eIx > 0 && IALPHABET[sArr[eIx]] < 0) {
eIx--;
}

// get the padding count (=) (0, 1 or 2)
int pad = sArr[eIx] == '=' ? (sArr[eIx - 1] == '=' ? 2 : 1) : 0; // Count '=' at end.
int cCnt = eIx - sIx + 1; // Content count including possible separators
int sepCnt = sLen > 76 ? (sArr[76] == '\r' ? cCnt / 78 : 0) << 1 : 0;

int len = ((cCnt - sepCnt) * 6 >> 3) - pad; // The number of decoded bytes
byte[] dArr = new byte[len]; // Preallocate byte[] of exact length

// Decode all but the last 0 - 2 bytes.
int d = 0;
for (int cc = 0, eLen = (len / 3) * 3; d < eLen; ) {

// Assemble three bytes into an int from four "valid" characters.
int i = ctoi(sArr[sIx++]) << 18 | ctoi(sArr[sIx++]) << 12 | ctoi(sArr[sIx++]) << 6 | ctoi(sArr[sIx++]);

// Add the bytes
dArr[d++] = (byte) (i >> 16);
dArr[d++] = (byte) (i >> 8);
dArr[d++] = (byte) i;

// If line separator, jump over it.
if (sepCnt > 0 && ++cc == 19) {
sIx += 2;
cc = 0;
}
}

if (d < len) {
// Decode last 1-3 bytes (incl '=') into 1-3 bytes
int i = 0;
for (int j = 0; sIx <= eIx - pad; j++) {
i |= ctoi(sArr[sIx++]) << (18 - j * 6);
}

for (int r = 16; d < len; r -= 8) {
dArr[d++] = (byte) (i >> r);
}
}

return dArr;
}

private static int ctoi(char c) {
int i = c > IALPHABET_MAX_INDEX ? -1 : IALPHABET[c];
if (i < 0) {
String msg = "Illegal base64 character: '" + c + "'";
throw new IllegalArgumentException(msg);
}
return i;
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
package com.alibaba.nacos.plugin.auth.impl.utils;

import org.junit.Assert;
import org.junit.Test;

/**
* Base64Decoder test.
*
* @author xYohn
* @date 2023/8/8
*/
public class Base64DecodeTest {
@Test
public void testStandardDecode() {
String origin = "aGVsbG8sbmFjb3MhdGVzdEJhc2U2NGVuY29kZQ==";
String expectDecodeOrigin = "hello,nacos!testBase64encode";
byte[] decodeOrigin = Base64Decode.decode(origin);
Assert.assertArrayEquals(decodeOrigin, expectDecodeOrigin.getBytes());
}

@Test
public void testNotStandardDecode() {
String notStandardOrigin = "SecretKey012345678901234567890123456789012345678901234567890123456789";
byte[] decodeNotStandardOrigin = Base64Decode.decode(notStandardOrigin);
String truncationOrigin = "SecretKey01234567890123456789012345678901234567890123456789012345678";
byte[] decodeTruncationOrigin = Base64Decode.decode(truncationOrigin);
Assert.assertArrayEquals(decodeNotStandardOrigin, decodeTruncationOrigin);
}
}

0 comments on commit 445fb90

Please sign in to comment.