All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.apache.ws.security.components.crypto.DERDecoder Maven / Gradle / Ivy

/**
 * 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.ws.security.components.crypto;

import java.math.BigInteger;
import org.apache.ws.security.WSSecurityException;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

/**
 * Provides the means to navigate through a DER-encoded byte array, to help
 * in decoding the contents.
 * 

* It maintains a "current position" in the array that advances with each * operation, providing a simple means to handle the type-length-value * encoding of DER. For example *

 *   decoder.expect(TYPE);
 *   int length = decoder.getLength();
 *   byte[] value = decoder.getBytes(len);
 * 
*/ public class DERDecoder { private static Log log = LogFactory.getLog(DERDecoder.class); /** DER type identifier for a bit string value */ public static final byte TYPE_BIT_STRING = 0x03; /** DER type identifier for a octet string value */ public static final byte TYPE_OCTET_STRING = 0x04; /** DER type identifier for a sequence value */ public static final byte TYPE_SEQUENCE = 0x30; private byte[] arr; private int pos; /** * Construct a DERDecoder for the given byte array. * * @param derEncoded the DER-encoded array to decode. * @throws WSSecurityException if the given array is null. */ public DERDecoder(byte[] derEncoded) throws WSSecurityException { if (derEncoded == null) { throw new WSSecurityException( WSSecurityException.UNSUPPORTED_SECURITY_TOKEN, "noSKIHandling", new Object[] { "Invalid DER string" } ); } arr = derEncoded; reset(); } /** * Reset the current position to the start of the array. */ public void reset() { pos = 0; } /** * Advance the current position by the given number of bytes. * * @param length the number of bytes to skip. * @throws WSSecurityException if length is negative. */ public void skip(int length) throws WSSecurityException { if (length < 0) { throw new WSSecurityException( WSSecurityException.UNSUPPORTED_SECURITY_TOKEN, "noSKIHandling", new Object[] { "Unsupported DER format" } ); } pos += length; } /** * Confirm that the byte at the current position matches the given value. * * @param val the expected next byte. * @throws WSSecurityException * if the current position is at the end of the array, or if the * byte at the current position doesn't match the expected value. */ public void expect(int val) throws WSSecurityException { expect((byte)(val & 0xFF)); } /** * Confirm that the byte at the current position matches the given value. * * @param val the expected next byte. * @throws WSSecurityException * if the current position is at the end of the array, or if the * byte at the current position doesn't match the expected value. */ public void expect(byte val) throws WSSecurityException { if (!test(val)) { log.debug("DER mismatch: expected " + val + ", got " + arr[pos]); throw new WSSecurityException( WSSecurityException.UNSUPPORTED_SECURITY_TOKEN, "noSKIHandling", new Object[] { "Invalid DER format" } ); } pos++; } /** * Test if the byte at the current position matches the given value. * * @param val the value to test for a match with the current byte. * @return true if the byte at the current position matches the given value. * @throws WSSecurityException if the current position is at the end of * the array. */ public boolean test(byte val) throws WSSecurityException { if (pos >= arr.length) { throw new WSSecurityException( WSSecurityException.UNSUPPORTED_SECURITY_TOKEN, "noSKIHandling", new Object[] { "Invalid DER format" } ); } return (arr[pos] == val); } /** * Get the DER length at the current position. *

* DER length is encoded as *

    *
  • If the first byte is 0x00 to 0x7F, it describes the actual length. *
  • If the first byte is 0x80 + n with 0The length value 0x80, used only in constructed types, is * defined as "indefinite length". *
* * @return the length, -1 for indefinite length. * @throws WSSecurityException * if the current position is at the end of the array or there is * an incomplete length specification. */ public int getLength() throws WSSecurityException { if (pos >= arr.length) { throw new WSSecurityException( WSSecurityException.UNSUPPORTED_SECURITY_TOKEN, "noSKIHandling", new Object[] { "Invalid DER format" } ); } int len; if ((arr[pos] & 0xFF) <= 0x7F) { len = arr[pos++]; } else if (arr[pos] == 0x80) { len = -1; pos++; } else { int nbytes = arr[pos++] & 0x7F; if (pos + nbytes > arr.length) { throw new WSSecurityException( WSSecurityException.UNSUPPORTED_SECURITY_TOKEN, "noSKIHandling", new Object[] { "Invalid DER format" } ); } byte[] lenBytes = new byte[nbytes]; System.arraycopy(arr, pos, lenBytes, 0, lenBytes.length); len = new BigInteger(1, lenBytes).intValue(); pos += nbytes; } return len; } /** * Return an array of bytes from the current position. * * @param length the number of bytes to return. * @return an array of the requested number of bytes from the current * position. * @throws WSSecurityException * if the current position is at the end of the array, or the * length is negative. */ public byte[] getBytes(int length) throws WSSecurityException { if (pos + length > arr.length) { throw new WSSecurityException( WSSecurityException.UNSUPPORTED_SECURITY_TOKEN, "noSKIHandling", new Object[] { "Invalid DER format" } ); } else if (length < 0) { throw new WSSecurityException( WSSecurityException.UNSUPPORTED_SECURITY_TOKEN, "noSKIHandling", new Object[] { "Unsupported DER format" } ); } byte[] value = new byte[length]; System.arraycopy(arr, pos, value, 0, length); pos += length; return value; } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy