Repository: cxf Updated Branches: refs/heads/master fc5026a90 -> 21d14505f
[CXF-5628] Fixes to Base64URLUtility and HmacUtils Project: http://git-wip-us.apache.org/repos/asf/cxf/repo Commit: http://git-wip-us.apache.org/repos/asf/cxf/commit/21d14505 Tree: http://git-wip-us.apache.org/repos/asf/cxf/tree/21d14505 Diff: http://git-wip-us.apache.org/repos/asf/cxf/diff/21d14505 Branch: refs/heads/master Commit: 21d14505faa3674855c7e1d43717ebe533e43595 Parents: fc5026a Author: Sergey Beryozkin <[email protected]> Authored: Thu Mar 20 10:29:09 2014 +0000 Committer: Sergey Beryozkin <[email protected]> Committed: Thu Mar 20 10:29:09 2014 +0000 ---------------------------------------------------------------------- .../oauth2/grants/code/DigestCodeVerifier.java | 14 +- .../oauth2/tokens/hawk/HawkAccessToken.java | 3 +- .../tokens/hawk/HawkAccessTokenValidator.java | 3 +- .../tokens/hawk/HawkAuthorizationScheme.java | 4 +- .../oauth2/tokens/hawk/HmacAlgorithm.java | 53 +++ .../security/oauth2/utils/Base64UrlUtility.java | 359 ++----------------- .../rs/security/oauth2/utils/HmacAlgorithm.java | 51 --- .../cxf/rs/security/oauth2/utils/HmacUtils.java | 112 +++--- .../oauth2/utils/MessageDigestGenerator.java | 6 +- .../security/oauth2/utils/OAuthConstants.java | 6 +- .../oauth2/provider/OAuthJSONProviderTest.java | 3 +- .../hawk/HawkAccessTokenValidatorTest.java | 1 - 12 files changed, 169 insertions(+), 446 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/cxf/blob/21d14505/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/grants/code/DigestCodeVerifier.java ---------------------------------------------------------------------- diff --git a/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/grants/code/DigestCodeVerifier.java b/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/grants/code/DigestCodeVerifier.java index 12e3dcc..e663e86 100644 --- a/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/grants/code/DigestCodeVerifier.java +++ b/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/grants/code/DigestCodeVerifier.java @@ -18,10 +18,6 @@ */ package org.apache.cxf.rs.security.oauth2.grants.code; -import java.io.StringWriter; - -import org.apache.cxf.common.util.Base64Exception; -import org.apache.cxf.rs.security.oauth2.provider.OAuthServiceException; import org.apache.cxf.rs.security.oauth2.utils.Base64UrlUtility; import org.apache.cxf.rs.security.oauth2.utils.MessageDigestGenerator; @@ -29,16 +25,10 @@ public class DigestCodeVerifier implements CodeVerifierTransformer { public String transformCodeVerifier(String codeVerifier) { MessageDigestGenerator mdg = new MessageDigestGenerator(); - byte[] digest = mdg.createDigest(codeVerifier, "SHA-256"); + byte[] digest = mdg.createDigest(codeVerifier, MessageDigestGenerator.ALGO_SHA_256); int length = digest.length > 128 / 8 ? 128 / 8 : digest.length; - StringWriter stringWriter = new StringWriter(); - try { - Base64UrlUtility.encode(digest, 0, length, stringWriter); - } catch (Base64Exception e) { - throw new OAuthServiceException("server_error", e); - } - return stringWriter.toString(); + return Base64UrlUtility.encodeChunk(digest, 0, length); } http://git-wip-us.apache.org/repos/asf/cxf/blob/21d14505/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/tokens/hawk/HawkAccessToken.java ---------------------------------------------------------------------- diff --git a/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/tokens/hawk/HawkAccessToken.java b/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/tokens/hawk/HawkAccessToken.java index 1b51db1..0745a18 100644 --- a/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/tokens/hawk/HawkAccessToken.java +++ b/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/tokens/hawk/HawkAccessToken.java @@ -20,7 +20,6 @@ package org.apache.cxf.rs.security.oauth2.tokens.hawk; import org.apache.cxf.rs.security.oauth2.common.Client; import org.apache.cxf.rs.security.oauth2.common.ServerAccessToken; -import org.apache.cxf.rs.security.oauth2.utils.HmacAlgorithm; import org.apache.cxf.rs.security.oauth2.utils.HmacUtils; import org.apache.cxf.rs.security.oauth2.utils.OAuthConstants; import org.apache.cxf.rs.security.oauth2.utils.OAuthUtils; @@ -77,7 +76,7 @@ public class HawkAccessToken extends ServerAccessToken { } private void setExtraParameters(HmacAlgorithm algo, String macKey) { - String theKey = macKey == null ? HmacUtils.generateSecret(algo) : macKey; + String theKey = macKey == null ? HmacUtils.generateKey(algo.getJavaName()) : macKey; super.getParameters().put(OAuthConstants.HAWK_TOKEN_KEY, theKey); super.getParameters().put(OAuthConstants.HAWK_TOKEN_ALGORITHM, http://git-wip-us.apache.org/repos/asf/cxf/blob/21d14505/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/tokens/hawk/HawkAccessTokenValidator.java ---------------------------------------------------------------------- diff --git a/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/tokens/hawk/HawkAccessTokenValidator.java b/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/tokens/hawk/HawkAccessTokenValidator.java index d8964a8..6e127b7 100644 --- a/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/tokens/hawk/HawkAccessTokenValidator.java +++ b/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/tokens/hawk/HawkAccessTokenValidator.java @@ -34,7 +34,6 @@ import org.apache.cxf.rs.security.oauth2.provider.AccessTokenValidator; import org.apache.cxf.rs.security.oauth2.provider.OAuthDataProvider; import org.apache.cxf.rs.security.oauth2.provider.OAuthServiceException; import org.apache.cxf.rs.security.oauth2.utils.AuthorizationUtils; -import org.apache.cxf.rs.security.oauth2.utils.HmacAlgorithm; import org.apache.cxf.rs.security.oauth2.utils.HmacUtils; import org.apache.cxf.rs.security.oauth2.utils.OAuthConstants; @@ -90,7 +89,7 @@ public class HawkAccessTokenValidator implements AccessTokenValidator { try { HmacAlgorithm hmacAlgo = HmacAlgorithm.toHmacAlgorithm(macAccessToken.getMacAlgorithm()); byte[] serverMacData = HmacUtils.computeHmac( - macAccessToken.getMacKey(), hmacAlgo, normalizedString); + macAccessToken.getMacKey(), hmacAlgo.getJavaName(), normalizedString); byte[] clientMacData = Base64Utility.decode(clientMacString); boolean validMac = Arrays.equals(serverMacData, clientMacData); http://git-wip-us.apache.org/repos/asf/cxf/blob/21d14505/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/tokens/hawk/HawkAuthorizationScheme.java ---------------------------------------------------------------------- diff --git a/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/tokens/hawk/HawkAuthorizationScheme.java b/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/tokens/hawk/HawkAuthorizationScheme.java index 2d97895..55e09e5 100644 --- a/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/tokens/hawk/HawkAuthorizationScheme.java +++ b/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/tokens/hawk/HawkAuthorizationScheme.java @@ -69,7 +69,9 @@ public class HawkAuthorizationScheme { public String toAuthorizationHeader(String macAlgo, String macSecret) { String data = getNormalizedRequestString(); - String signature = HmacUtils.computeSignature(macAlgo, macSecret, data); + String signature = HmacUtils.encodeHmacString(macSecret, + HmacAlgorithm.toHmacAlgorithm(macAlgo).getJavaName(), + data); StringBuilder sb = new StringBuilder(); sb.append(OAuthConstants.HAWK_AUTHORIZATION_SCHEME).append(" "); http://git-wip-us.apache.org/repos/asf/cxf/blob/21d14505/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/tokens/hawk/HmacAlgorithm.java ---------------------------------------------------------------------- diff --git a/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/tokens/hawk/HmacAlgorithm.java b/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/tokens/hawk/HmacAlgorithm.java new file mode 100644 index 0000000..d9aaa97 --- /dev/null +++ b/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/tokens/hawk/HmacAlgorithm.java @@ -0,0 +1,53 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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 org.apache.cxf.rs.security.oauth2.tokens.hawk; + +import org.apache.cxf.rs.security.oauth2.utils.OAuthConstants; + +public enum HmacAlgorithm { + + HmacSHA1(OAuthConstants.HMAC_ALGO_SHA_1), + HmacSHA256(OAuthConstants.HMAC_ALGO_SHA_256); + + private final String oauthName; + + private HmacAlgorithm(String oauthName) { + this.oauthName = oauthName; + } + + public String getOAuthName() { + return oauthName; + } + + public String getJavaName() { + return name(); + } + + public static HmacAlgorithm toHmacAlgorithm(String value) { + if (OAuthConstants.HMAC_ALGO_SHA_1.equals(value)) { + return HmacSHA1; + } + if (OAuthConstants.HMAC_ALGO_SHA_256.equals(value)) { + return HmacSHA256; + } + return null; + } + +} \ No newline at end of file http://git-wip-us.apache.org/repos/asf/cxf/blob/21d14505/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/utils/Base64UrlUtility.java ---------------------------------------------------------------------- diff --git a/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/utils/Base64UrlUtility.java b/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/utils/Base64UrlUtility.java index 5d1075d..76beabf 100644 --- a/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/utils/Base64UrlUtility.java +++ b/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/utils/Base64UrlUtility.java @@ -20,361 +20,62 @@ package org.apache.cxf.rs.security.oauth2.utils; /** - * Base64 URL Encoding/Decoding utility (character 62 is '-', 63 - '_') - * TODO: - * - encoding: exclude padding characters by default, - * - decoding: calculate a number of missing padding characters - * based on a number of base64url encoded octets - * - * - once the above two points are addressed, consider extracting - * most of Base64Utility into Base64EncoderDecoder and extending it - * with Base64UrlEncoderDecoder to minimize the duplication + * Base64 URL Encoding/Decoding utility. + * + * Character 62 ('+') is '-', Character 63 ('/') is '_'; + * Padding characters are dropped after the encoding. * */ -import java.io.IOException; -import java.io.OutputStream; -import java.io.StringWriter; import java.io.UnsupportedEncodingException; -import java.io.Writer; import java.util.logging.Logger; import org.apache.cxf.common.i18n.Message; import org.apache.cxf.common.logging.LogUtils; import org.apache.cxf.common.util.Base64Exception; +import org.apache.cxf.common.util.Base64Utility; public final class Base64UrlUtility { - private static final Logger LOG = LogUtils.getL7dLogger(Base64UrlUtility.class); - - private static final String ENCODED_PAD = "%3D"; - - // Base 64 URL character set - // - private static final char[] BCS = { - 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', - 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', - 'U', 'V', 'W', 'X', 'Y', 'Z', 'a', 'b', 'c', 'd', - 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', - 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', - 'y', 'z', '0', '1', '2', '3', '4', '5', '6', '7', - '8', '9', '-', '_' - }; - - // base 64 wadding - private static final char PAD = '='; - - // size of base 64 decode table - private static final int BDTSIZE = 128; - - // base 64 decode table - private static final byte[] BDT = new byte[128]; - - - private static final int PAD_SIZE0 = 1; - private static final int PAD_SIZE4 = 2; - private static final int PAD_SIZE8 = 3; - - // class static intializer for building decode table - static { - for (int i = 0; i < BDTSIZE; i++) { - BDT[i] = Byte.MAX_VALUE; - } - - for (int i = 0; i < BCS.length; i++) { - BDT[BCS[i]] = (byte)i; - } - } - private Base64UrlUtility() { //utility class, never constructed } - /** - * The <code>decode_chunk</code> routine decodes a chunk of data - * into its native encoding. - * - * base64 encodes each 3 octets of data into 4 characters from a - * limited 64 character set. The 3 octets are joined to form - * 24 bits which are then split into 4 x 6bit values. Each 6 bit - * value is then used as an index into the 64 character table of - * base64 chars. If the total data length is not a 3 octet multiple - * the '=' char is used as padding for the final 4 char group, - * either 1 octet + '==' or 2 octets + '='. - * - * @param id The input data to be processed - * @param o The offset from which to begin processing - * @param l The length (bound) at which processing is to end - * @return The decoded data - * @exception Base64Exception Thrown is processing fails due to - * formatting exceptions in the encoded data - */ - public static byte[] decodeChunk(char[] id, - int o, - int l) - throws Base64Exception { - - // Keep it simple - must be >= 4. Unpadded - // base64 data contain < 3 octets is invalid. - // - if ((l - o) < 4) { - return null; - } - - char[] ib = new char[4]; - int ibcount = 0; - - // cryan. Calc the num of octets. Each 4 chars of base64 chars - // (representing 24 bits) encodes 3 octets. - // - int octetCount = 3 * (l / 4); - - // Final 4 chars may contain 3 octets or padded to contain - // 1 or 2 octets. - // - if (id[l - 1] == PAD) { - // TT== means last 4 chars encode 8 bits (ie subtract 2) - // TTT= means last 4 chars encode 16 bits (ie subtract 1) - octetCount -= (id[l - 2] == PAD) ? 2 : 1; - } - - byte[] ob = new byte[octetCount]; - int obcount = 0; - - for (int i = o; i < o + l && i < id.length; i++) { - if (id[i] == PAD - || id[i] < BDT.length - && BDT[id[i]] != Byte.MAX_VALUE) { - - ib[ibcount++] = id[i]; - - // Decode each 4 char sequence. - // - if (ibcount == ib.length) { - ibcount = 0; - obcount += processEncodeme(ib, ob, obcount); - } - } - } - - if (obcount != ob.length) { - byte []tmp = new byte[obcount]; - System.arraycopy(ob, 0, tmp, 0, obcount); - ob = tmp; - } - - return ob; - } - - public static byte[] decode(String id) throws Base64Exception { - int count = 0; - while (id.endsWith(ENCODED_PAD)) { - id = id.substring(0, id.length() - ENCODED_PAD.length()); - count++; - } - for (int i = 0; i < count; i++) { - id += PAD; - } - - try { - char[] cd = id.toCharArray(); - return decodeChunk(cd, 0, cd.length); - } catch (Exception e) { - LOG.warning("Invalid base64 encoded string : " + id); - throw new Base64Exception(new Message("BASE64_RUNTIME_EXCEPTION", LOG), e); - } - } - - public static void decode(char[] id, - int o, - int l, - OutputStream ostream) - throws Base64Exception { - - try { - ostream.write(decodeChunk(id, o, l)); - } catch (Exception e) { - LOG.warning("Invalid base64 encoded string : " + new String(id)); - throw new Base64Exception(new Message("BASE64_RUNTIME_EXCEPTION", LOG), e); - } - } - - public static void decode(String id, - OutputStream ostream) - throws Base64Exception { - - try { - char[] cd = id.toCharArray(); - ostream.write(decodeChunk(cd, 0, cd.length)); - } catch (IOException ioe) { - throw new Base64Exception(new Message("BASE64_DECODE_IOEXCEPTION", LOG), ioe); - } catch (Exception e) { - LOG.warning("Invalid base64 encoded string : " + id); - throw new Base64Exception(new Message("BASE64_RUNTIME_EXCEPTION", LOG), e); - } - } - - // Returns base64 representation of specified byte array. - // - public static String encode(byte[] id) { - char[] cd = encodeChunk(id, 0, id.length); - return new String(cd, 0, cd.length); - } - - // Returns base64 representation of specified byte array. - // - public static char[] encodeChunk(byte[] id, - int o, - int l) { - if (l <= 0) { - return null; - } - - char[] out; - - // If not a multiple of 3 octets then a final padded 4 char - // slot is needed. - // - if ((l - o) % 3 == 0) { - out = new char[l / 3 * 4]; - } else { - out = new char[l / 3 * 4 + 4]; - } - - int rindex = o; - int windex = 0; - int rest = l - o; - - while (rest >= 3) { - int i = ((id[rindex] & 0xff) << 16) - + ((id[rindex + 1] & 0xff) << 8) - + (id[rindex + 2] & 0xff); - - out[windex++] = BCS[i >> 18]; - out[windex++] = BCS[(i >> 12) & 0x3f]; - out[windex++] = BCS[(i >> 6) & 0x3f]; - out[windex++] = BCS[i & 0x3f]; - rindex += 3; - rest -= 3; - } - - if (rest == 1) { - int i = id[rindex] & 0xff; - out[windex++] = BCS[i >> 2]; - out[windex++] = BCS[(i << 4) & 0x3f]; - out[windex++] = PAD; - out[windex++] = PAD; - } else if (rest == 2) { - int i = ((id[rindex] & 0xff) << 8) + (id[rindex + 1] & 0xff); - out[windex++] = BCS[i >> 10]; - out[windex++] = BCS[(i >> 4) & 0x3f]; - out[windex++] = BCS[(i << 2) & 0x3f]; - out[windex++] = PAD; - } - return out; + public static byte[] decode(String encoded) throws Base64Exception { + encoded = encoded.replace("-", "+").replace('_', '/'); + switch (encoded.length() % 4) { + case 0: + break; + case 2: + encoded += "=="; + break; + case 3: + encoded += "="; + break; + default: + throw new Base64Exception(new Message("BASE64_RUNTIME_EXCEPTION", LOG)); + } + return Base64Utility.decode(encoded); } - // - // Outputs base64 representation of the specified byte array - // to a byte stream. - // - public static void encodeChunk(byte[] id, - int o, - int l, - OutputStream ostream) throws Base64Exception { + public static String encode(String str) throws Base64Exception { try { - ostream.write(new String(encodeChunk(id, o, l)).getBytes()); - } catch (IOException e) { - throw new Base64Exception(new Message("BASE64_ENCODE_IOEXCEPTION", LOG), e); - } - } - - public static String encode(String value) throws Base64Exception { - StringWriter writer = new StringWriter(); - Base64UrlUtility.encode(value, writer); - return writer.toString(); - } - - public static void encode(String value, Writer writer) throws Base64Exception { - byte[] chunk = null; - try { - chunk = value.getBytes("UTF-8"); + return encode(str.getBytes("UTF-8")); } catch (UnsupportedEncodingException ex) { - // won't happen + throw new RuntimeException(ex); } - Base64UrlUtility.encode(chunk, 0, chunk.length, writer); - } - - // Outputs base64 representation of the specified byte - // array to a character stream. - // - public static void encode(byte[] id, - int o, - int l, - Writer writer) throws Base64Exception { - try { - writer.write(encodeChunk(id, o, l)); - } catch (IOException e) { - throw new Base64Exception(new Message("BASE64_ENCODE_WRITER_IOEXCEPTION", LOG), e); - } + public static String encode(byte[] id) { + return encodeChunk(id, 0, id.length); } - - //---- Private static methods -------------------------------------- - - /** - * The <code>process</code> routine processes an atomic base64 - * unit of encoding (encodeme) into its native encoding. This class is - * used by decode routines to do the grunt work of decoding - * base64 encoded information - * - * @param ib Input character buffer of encoded bytes - * @param ob Output byte buffer of decoded bytes - * @param p Pointer to the encodeme of interest - * @return The decoded encodeme - * @exception Base64Exception Thrown is processing fails due to - * formatting exceptions in the encoded data - */ - private static int processEncodeme(char[] ib, - byte[] ob, - int p) - throws Base64Exception { - - - int spad = PAD_SIZE8; - if (ib[3] == PAD) { - spad = PAD_SIZE4; - } - if (ib[2] == PAD) { - spad = PAD_SIZE0; - } - - int b0 = BDT[ib[0]]; - int b1 = BDT[ib[1]]; - int b2 = BDT[ib[2]]; - int b3 = BDT[ib[3]]; - - switch (spad) { - case PAD_SIZE0: - ob[p] = (byte)(b0 << 2 & 0xfc | b1 >> 4 & 0x3); - return PAD_SIZE0; - case PAD_SIZE4: - ob[p++] = (byte)(b0 << 2 & 0xfc | b1 >> 4 & 0x3); - ob[p] = (byte)(b1 << 4 & 0xf0 | b2 >> 2 & 0xf); - return PAD_SIZE4; - case PAD_SIZE8: - ob[p++] = (byte)(b0 << 2 & 0xfc | b1 >> 4 & 0x3); - ob[p++] = (byte)(b1 << 4 & 0xf0 | b2 >> 2 & 0xf); - ob[p] = (byte)(b2 << 6 & 0xc0 | b3 & 0x3f); - return PAD_SIZE8; - default: - // We should never get here - throw new IllegalStateException(); - } - } + public static String encodeChunk(byte[] id, int offset, int length) { + String encoded = new String(Base64Utility.encodeChunk(id, offset, length)); + return encoded.replace("+", "-").replace('/', '_').replace("=", ""); + } + } http://git-wip-us.apache.org/repos/asf/cxf/blob/21d14505/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/utils/HmacAlgorithm.java ---------------------------------------------------------------------- diff --git a/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/utils/HmacAlgorithm.java b/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/utils/HmacAlgorithm.java deleted file mode 100644 index 05f8deb..0000000 --- a/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/utils/HmacAlgorithm.java +++ /dev/null @@ -1,51 +0,0 @@ -/** - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you 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 org.apache.cxf.rs.security.oauth2.utils; - - -public enum HmacAlgorithm { - HmacSHA1(HmacUtils.ALGO_HMAC_SHA_1), - HmacSHA256(HmacUtils.ALGO_HMAC_SHA_256); - - private final String oauthName; - - private HmacAlgorithm(String oauthName) { - this.oauthName = oauthName; - } - - public String getOAuthName() { - return oauthName; - } - - public String getJavaName() { - return name(); - } - - public static HmacAlgorithm toHmacAlgorithm(String value) { - if (HmacUtils.ALGO_HMAC_SHA_1.equals(value)) { - return HmacSHA1; - } - if (HmacUtils.ALGO_HMAC_SHA_256.equals(value)) { - return HmacSHA256; - } - return null; - } - -} \ No newline at end of file http://git-wip-us.apache.org/repos/asf/cxf/blob/21d14505/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/utils/HmacUtils.java ---------------------------------------------------------------------- diff --git a/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/utils/HmacUtils.java b/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/utils/HmacUtils.java index c6ba06c..1e17027 100644 --- a/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/utils/HmacUtils.java +++ b/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/utils/HmacUtils.java @@ -19,8 +19,13 @@ package org.apache.cxf.rs.security.oauth2.utils; import java.io.UnsupportedEncodingException; +import java.security.InvalidAlgorithmParameterException; import java.security.InvalidKeyException; +import java.security.Key; import java.security.NoSuchAlgorithmException; +import java.security.NoSuchProviderException; +import java.security.Provider; +import java.security.spec.AlgorithmParameterSpec; import javax.crypto.KeyGenerator; import javax.crypto.Mac; @@ -30,71 +35,90 @@ import org.apache.cxf.common.util.Base64Utility; import org.apache.cxf.rs.security.oauth2.provider.OAuthServiceException; public final class HmacUtils { - public static final String ALGO_HMAC_SHA_1 = "hmac-sha-1"; - public static final String ALGO_HMAC_SHA_256 = "hmac-sha-256"; private HmacUtils() { } - public static String computeSignature(String macAlgoOAuthName, String macSecret, String data) { - HmacAlgorithm theAlgo = HmacAlgorithm.toHmacAlgorithm(macAlgoOAuthName); - return computeHmacString(macSecret, theAlgo.getJavaName(), data); + public static String encodeHmacString(String macSecret, String macAlgoJavaName, String data) { + return Base64Utility.encode(computeHmac(macSecret, macAlgoJavaName, data)); } - /** - * Computes HMAC value using the given parameters. - * - * @param macSecret - * @param macAlgorithm Should be one of HmacSHA1 or HmacSHA256 - * @param data - * @return Base64 encoded string representation of the computed hmac value - */ - public static String computeHmacString(String macSecret, String macAlgoJavaName, String data) { - return new String(Base64Utility.encode(computeHmac(macSecret, macAlgoJavaName, data))); + public static String encodeHmacString(String macSecret, String macAlgoJavaName, String data, boolean urlSafe) { + byte[] bytes = computeHmac(macSecret, macAlgoJavaName, data); + return urlSafe ? Base64UrlUtility.encode(bytes) : Base64Utility.encode(bytes); } - /** - * Computes HMAC value using the given parameters. - * - * @param macKey - * @param macAlgorithm - * @param data - * @return Computed HMAC value. - */ - public static byte[] computeHmac(String key, HmacAlgorithm algo, String data) { - return computeHmac(key, algo.getJavaName(), data); + public static Mac getMac(String macAlgoJavaName) { + return getMac(macAlgoJavaName, (String)null); + } + + public static Mac getMac(String macAlgoJavaName, String provider) { + try { + return provider == null ? Mac.getInstance(macAlgoJavaName) : Mac.getInstance(macAlgoJavaName, provider); + } catch (NoSuchAlgorithmException e) { + throw new OAuthServiceException(e); + } catch (NoSuchProviderException e) { + throw new OAuthServiceException(e); + } + } + + public static Mac getMac(String macAlgoJavaName, Provider provider) { + try { + return Mac.getInstance(macAlgoJavaName, provider); + } catch (NoSuchAlgorithmException e) { + throw new OAuthServiceException(e); + } } - /** - * Computes HMAC value using the given parameters. - * - * @param macKey - * @param macAlgorithm - * @param data - * @return Computed HMAC value. - */ public static byte[] computeHmac(String key, String macAlgoJavaName, String data) { + Mac mac = getMac(macAlgoJavaName); + return computeHmac(key, mac, data); + } + + public static byte[] computeHmac(byte[] key, String macAlgoJavaName, String data) { + Mac mac = getMac(macAlgoJavaName); + return computeHmac(key, mac, data); + } + + public static byte[] computeHmac(String key, Mac hmac, String data) { + try { + return computeHmac(key.getBytes("UTF-8"), hmac, data); + } catch (UnsupportedEncodingException e) { + throw new OAuthServiceException(e); + } + } + + public static byte[] computeHmac(byte[] key, Mac hmac, String data) { + SecretKeySpec secretKey = new SecretKeySpec(key, hmac.getAlgorithm()); + return computeHmac(secretKey, hmac, data); + } + + public static byte[] computeHmac(Key secretKey, Mac hmac, String data) { + return computeHmac(secretKey, hmac, null, data); + } + + public static byte[] computeHmac(Key secretKey, Mac hmac, AlgorithmParameterSpec spec, String data) { try { - Mac hmac = Mac.getInstance(macAlgoJavaName); - SecretKeySpec secretKey = new SecretKeySpec(key.getBytes("UTF-8"), macAlgoJavaName); - hmac.init(secretKey); + if (spec == null) { + hmac.init(secretKey); + } else { + hmac.init(secretKey, spec); + } return hmac.doFinal(data.getBytes()); - } catch (NoSuchAlgorithmException e) { - throw new OAuthServiceException(OAuthConstants.INVALID_REQUEST, e); } catch (InvalidKeyException e) { - throw new OAuthServiceException(OAuthConstants.INVALID_REQUEST, e); - } catch (UnsupportedEncodingException e) { - throw new OAuthServiceException(OAuthConstants.INVALID_REQUEST, e); + throw new OAuthServiceException(e); + } catch (InvalidAlgorithmParameterException e) { + throw new OAuthServiceException(e); } } - public static String generateSecret(HmacAlgorithm algo) { + public static String generateKey(String algo) { try { - KeyGenerator keyGen = KeyGenerator.getInstance(algo.name()); + KeyGenerator keyGen = KeyGenerator.getInstance(algo); return Base64Utility.encode(keyGen.generateKey().getEncoded()); } catch (NoSuchAlgorithmException e) { - throw new OAuthServiceException(OAuthConstants.SERVER_ERROR, e); + throw new OAuthServiceException(e); } } http://git-wip-us.apache.org/repos/asf/cxf/blob/21d14505/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/utils/MessageDigestGenerator.java ---------------------------------------------------------------------- diff --git a/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/utils/MessageDigestGenerator.java b/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/utils/MessageDigestGenerator.java index fbde43b..15d4870 100644 --- a/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/utils/MessageDigestGenerator.java +++ b/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/utils/MessageDigestGenerator.java @@ -29,7 +29,11 @@ import org.apache.cxf.rs.security.oauth2.provider.OAuthServiceException; * random values */ public class MessageDigestGenerator { - private String algorithm = "MD5"; + public static final String ALGO_SHA_1 = "SHA-1"; + public static final String ALGO_SHA_256 = "SHA-256"; + public static final String ALGO_MD5 = "MD5"; + + private String algorithm = ALGO_MD5; public String generate(byte[] input) throws OAuthServiceException { if (input == null) { http://git-wip-us.apache.org/repos/asf/cxf/blob/21d14505/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/utils/OAuthConstants.java ---------------------------------------------------------------------- diff --git a/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/utils/OAuthConstants.java b/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/utils/OAuthConstants.java index 5a0c181..25fae18 100644 --- a/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/utils/OAuthConstants.java +++ b/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/utils/OAuthConstants.java @@ -59,7 +59,7 @@ public final class OAuthConstants { // CXF-specific public static final String REFRESH_TOKEN_TYPE = "refresh"; - // MAC token parameters + // Hawk token parameters // Set by Access Token Service public static final String HAWK_TOKEN_KEY = "secret"; public static final String HAWK_TOKEN_ALGORITHM = "algorithm"; @@ -71,6 +71,10 @@ public final class OAuthConstants { public static final String HAWK_TOKEN_NONCE = "nonce"; public static final String HAWK_TOKEN_SIGNATURE = "mac"; + // Mac/Hawk HMAC algorithm names + public static final String HMAC_ALGO_SHA_1 = "hmac-sha-1"; + public static final String HMAC_ALGO_SHA_256 = "hmac-sha-256"; + // Token Authorization schemes public static final String BEARER_AUTHORIZATION_SCHEME = "Bearer"; public static final String HAWK_AUTHORIZATION_SCHEME = "Hawk"; http://git-wip-us.apache.org/repos/asf/cxf/blob/21d14505/rt/rs/security/oauth-parent/oauth2/src/test/java/org/apache/cxf/rs/security/oauth2/provider/OAuthJSONProviderTest.java ---------------------------------------------------------------------- diff --git a/rt/rs/security/oauth-parent/oauth2/src/test/java/org/apache/cxf/rs/security/oauth2/provider/OAuthJSONProviderTest.java b/rt/rs/security/oauth-parent/oauth2/src/test/java/org/apache/cxf/rs/security/oauth2/provider/OAuthJSONProviderTest.java index 9754256..988d329 100644 --- a/rt/rs/security/oauth-parent/oauth2/src/test/java/org/apache/cxf/rs/security/oauth2/provider/OAuthJSONProviderTest.java +++ b/rt/rs/security/oauth-parent/oauth2/src/test/java/org/apache/cxf/rs/security/oauth2/provider/OAuthJSONProviderTest.java @@ -29,7 +29,6 @@ import javax.ws.rs.core.MediaType; import org.apache.cxf.jaxrs.impl.MetadataMap; import org.apache.cxf.rs.security.oauth2.common.ClientAccessToken; -import org.apache.cxf.rs.security.oauth2.utils.HmacUtils; import org.apache.cxf.rs.security.oauth2.utils.OAuthConstants; import org.junit.Assert; @@ -109,7 +108,7 @@ public class OAuthJSONProviderTest extends Assert { token.setApprovedScope("read"); Map<String, String> params = new LinkedHashMap<String, String>(); params.put(OAuthConstants.HAWK_TOKEN_KEY, "test_mac_secret"); - params.put(OAuthConstants.HAWK_TOKEN_ALGORITHM, HmacUtils.ALGO_HMAC_SHA_1); + params.put(OAuthConstants.HAWK_TOKEN_ALGORITHM, OAuthConstants.HMAC_ALGO_SHA_1); params.put("my_parameter", "http://abc"); token.setParameters(params); http://git-wip-us.apache.org/repos/asf/cxf/blob/21d14505/rt/rs/security/oauth-parent/oauth2/src/test/java/org/apache/cxf/rs/security/oauth2/tokens/hawk/HawkAccessTokenValidatorTest.java ---------------------------------------------------------------------- diff --git a/rt/rs/security/oauth-parent/oauth2/src/test/java/org/apache/cxf/rs/security/oauth2/tokens/hawk/HawkAccessTokenValidatorTest.java b/rt/rs/security/oauth-parent/oauth2/src/test/java/org/apache/cxf/rs/security/oauth2/tokens/hawk/HawkAccessTokenValidatorTest.java index 49a8720..b034016 100644 --- a/rt/rs/security/oauth-parent/oauth2/src/test/java/org/apache/cxf/rs/security/oauth2/tokens/hawk/HawkAccessTokenValidatorTest.java +++ b/rt/rs/security/oauth-parent/oauth2/src/test/java/org/apache/cxf/rs/security/oauth2/tokens/hawk/HawkAccessTokenValidatorTest.java @@ -28,7 +28,6 @@ import org.apache.cxf.rs.security.oauth2.client.HttpRequestProperties; import org.apache.cxf.rs.security.oauth2.common.AccessTokenValidation; import org.apache.cxf.rs.security.oauth2.common.Client; import org.apache.cxf.rs.security.oauth2.provider.OAuthDataProvider; -import org.apache.cxf.rs.security.oauth2.utils.HmacAlgorithm; import org.apache.cxf.rs.security.oauth2.utils.OAuthConstants; import org.easymock.EasyMock;
