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

net.freeutils.util.DERParser Maven / Gradle / Ivy

The newest version!
/*
 *  Copyright © 2003-2024 Amichai Rothman
 *
 *  This file is part of JElementary - the Java Elementary Utilities package.
 *
 *  JElementary is free software: you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation, either version 2 of the License, or
 *  (at your option) any later version.
 *
 *  JElementary 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 General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with JElementary.  If not, see .
 *
 *  For additional info see https://www.freeutils.net/source/jelementary/
 */

package net.freeutils.util;

import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;

/**
 * An X.690 ASN.1 DER data parser.
 * 

* The current implementation is very basic and supports only a small part of the spec. */ public class DERParser { final InputStream in; int tag; long len; /** * Constructs a DERParser for parsing the DER data in the given stream. * * @param in the DER data */ public DERParser(InputStream in) { this.in = in; } /** * Constructs a DERParser for parsing the DER data in the given byte array. * * @param data the DER data */ public DERParser(byte[] data) { this(new ByteArrayInputStream(data)); } /** * Reads a single byte of data from the stream as an integer. * * @return the read byte of data * @throws IOException if an error occurs or the end of stream has been reached */ private int read() throws IOException { int b = in.read(); if (b < 0) throw new IOException("unexpected end of stream"); return b; } /** * Reads a tag field from the stream. * * @return the read tag * @throws IOException if an error occurs * @throws UnsupportedOperationException if attempting to read a long form tag */ private int readTag() throws IOException { int tag = read(); if ((tag & 0x1f) == 0x1f) throw new UnsupportedOperationException("long tags are not supported yet"); return tag; } /** * Reads a length field from the stream. * * @return the read tag * @throws IOException if an error occurs * @throws UnsupportedOperationException if attempting to read a length value more than 7 bytes long */ private long readLength() throws IOException { long len = read(); if ((len & 0x80) != 0) { int octets = (int)len & 0x7f; if (octets > 7) throw new UnsupportedOperationException("length greater than 7 bytes is not supported"); len = 0; for (int i = 0; i < octets; i++) len = len << 8 | read(); } return len; } /** * Reads the next value's tag and length from the stream, making it the new current value. *

* The field data must be read using {@link #getContent}, {@link #parseContent()} * or {@link #skipContent()} before this method is called again. * * @throws IOException if an error occurs */ public void next() throws IOException { tag = readTag(); len = readLength(); } /** * Reads the next value's tag and length fields from the stream, making it the new current value, * while ensuring that the tag matches the given expected tag. *

* The field data must be read using {@link #getContent}, {@link #parseContent()} * or {@link #skipContent()} before this method is called again. * * @param expectedTag the expected tag * @throws IOException if an error occurs or the read tag does not match the expected tag */ public void next(int expectedTag) throws IOException { next(); if (tag != expectedTag) throw new IOException("unexpected tag " + tag); } /** * Returns the tag of the current value. * * @return the tag of the current value */ public int getTag() { return tag; } /** * Returns the length of the current value. * * @return the length of the current value */ public long getLength() { return len; } /** * Skips the content of the current value. * * @throws IOException if an error occurs */ public void skipContent() throws IOException { getContent(); // TODO: optimize to skip without reading } /** * Reads the raw content of the current value. * * @return the raw content of the current value * @throws IOException if an error occurs */ public byte[] getContent() throws IOException { byte[] data = new byte[(int)len]; int read = in.read(data); // TODO: read fully if (read < len) throw new IOException("unexpected end of stream (missing data)"); return data; } /** * Reads the content of the current value * and returns a {@code DERParser} to parse it. * * @return a parser for the content of the current value * @throws IOException if an error occurs */ public DERParser parseContent() throws IOException { return new DERParser(getContent()); // TODO: use substream instead of array } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy