/*
* JBoss, Home of Professional Open Source.
* Copyright 2012, Red Hat, Inc., and individual contributors
* as indicated by the @author tags. See the copyright.txt file in the
* distribution for a full listing of individual contributors.
*
* This is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as
* published by the Free Software Foundation; either version 2.1 of
* the License, or (at your option) any later version.
*
* This software is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this software; if not, write to the Free
* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
* 02110-1301 USA, or see the FSF site: http://www.fsf.org.
*/
package org.picketlink.json.util;
import java.text.ParseException;
public class JOSEUtil {
/**
* Checks the specified arrays for equality in constant time. Intended to mitigate timing attacks.
*
* @param a The first array. Must not be {@code null}.
* @param b The second array. Must not be {@code null}.
*
* @return {@code true} if the two arrays are equal, else {@code false}.
*/
public static boolean constantTimeAreEqual(final byte[] a, final byte[] b) {
// From http://codahale.com/a-lesson-in-timing-attacks/
if (a.length != b.length) {
return false;
}
int result = 0;
for (int i = 0; i < a.length; i++) {
result |= a[i] ^ b[i];
}
return result == 0;
}
/**
* Splits a serialized JOSE object into its Base64URL-encoded parts.
*
* @param s The serialized JOSE object to split. Must not be {@code null}.
*
* @return The JOSE Base64URL-encoded parts (three for plain text and JWS objects, five for JWE objects).
*
* @throws ParseException If the specified string couldn't be split into three or five Base64URL-encoded parts.
*/
public static String[] split(final String s)
throws ParseException {
// We must have 2 (JWS) or 4 dots (JWE)
// String.split() cannot handle empty parts
final int dot1 = s.indexOf(".");
if (dot1 == -1) {
throw new ParseException("Invalid serialized plain/JWS/JWE object: Missing part delimiters", 0);
}
final int dot2 = s.indexOf(".", dot1 + 1);
if (dot2 == -1) {
throw new ParseException("Invalid serialized plain/JWS/JWE object: Missing second delimiter", 0);
}
// Third dot for JWE only
final int dot3 = s.indexOf(".", dot2 + 1);
if (dot3 == -1) {
// Two dots only? -> We have a JWS
String[] parts = new String[3];
parts[0] = new String(s.substring(0, dot1));
parts[1] = new String(s.substring(dot1 + 1, dot2));
parts[2] = new String(s.substring(dot2 + 1));
return parts;
}
// Fourth final dot for JWE
final int dot4 = s.indexOf(".", dot3 + 1);
if (dot4 == -1) {
throw new ParseException("Invalid serialized JWE object: Missing fourth delimiter", 0);
}
if (dot4 != -1 && s.indexOf(".", dot4 + 1) != -1) {
throw new ParseException("Invalid serialized plain/JWS/JWE object: Too many part delimiters", 0);
}
// Four dots -> five parts
String[] parts = new String[5];
parts[0] = new String(s.substring(0, dot1));
parts[1] = new String(s.substring(dot1 + 1, dot2));
parts[2] = new String(s.substring(dot2 + 1, dot3));
parts[3] = new String(s.substring(dot3 + 1, dot4));
parts[4] = new String(s.substring(dot4 + 1));
return parts;
}
}