derencoder.java

来自「JAVA的加密库之一」· Java 代码 · 共 525 行 · 第 1/2 页

JAVA
525
字号
		cat.debug("<== encodeOctetString()");
	}

	public void encodeUTCTime(IType obj, Date val) throws IOException {
		cat.debug("==> encodeUTCTime()");

		Tag tag = obj.tag();
		cat.info("   tag=\""+tag+"\"");
		cat.info("   val="+String.valueOf(val));

		SimpleDateFormat sdf = new SimpleDateFormat("yyMMddHHmmss'Z'");
		sdf.setTimeZone(TimeZone.getTimeZone("UTC"));
		byte[] ba = sdf.format(val).getBytes();
		if (tag.isExplicit() && !tag.isUniversal())
			ba = toTLV(Tag.UTC_TIME, ba);
		synchronized (out) {
			encode(tag);
			encode(ba.length); // write the length
			write(ba); // and finally the object's data
			flush();
		}

		cat.debug("<== encodeUTCTime()");
	}

	public void encodeGeneralizedTime(IType obj, Date val) throws IOException {
		cat.debug("==> encodeGeneralizedTime()");

		Tag tag = obj.tag();
		cat.info("   tag=\""+tag+"\"");
		cat.info("   val="+String.valueOf(val));

		SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMddHHmmss'.'SSS'Z'");
		sdf.setTimeZone(TimeZone.getTimeZone("UTC"));
		byte[] ba = sdf.format(val).getBytes();
		if (tag.isExplicit() && !tag.isUniversal())
			ba = toTLV(Tag.GENERALIZED_TIME, ba);
		synchronized (out) {
			encode(tag);
			encode(ba.length); // write the length
			write(ba); // and finally the object's data
			flush();
		}

		cat.debug("<== encodeGeneralizedTime()");
	}

	public void encodeStructure(IIterativeType obj) throws IOException {
		cat.debug("==> encodeStructure()");

		Tag tag = obj.tag();
		cat.info("   tag=\""+tag+"\"");

		ByteArrayOutputStream baos = new ByteArrayOutputStream();
		ASNWriter local = (ASNWriter) this.clone();
		local.open(baos);
		Object element;
		IType t;
		ArrayList al;
		for (Iterator it = obj.iterator(); it.hasNext(); ) {
		   element = it.next();
		   if (element instanceof IType) {
   			t = (Type) element;
	   		cat.info("Encoding (simple) "+t.getClass().getName()+"...");
		   	t.encode(local);
		   } else // SEQUENCE/SET OF
		      for (Iterator ali = ((ArrayList) element).iterator(); ali.hasNext(); ) {
   			   t = (Type) ali.next();
	   		   cat.info("Encoding (compound) "+t.getClass().getName()+"...");
		   	   t.encode(local);
		      }
		}

		local.close();
		byte[] ba = baos.toByteArray();

		if (tag.isExplicit() && !tag.isUniversal())
			ba = toTLV(Tag.SEQUENCE, ba);
		synchronized (out) {
			encode(tag);
			encode(ba.length); // write the length
			write(ba); // and finally the object's data
			flush();
		}

		cat.debug("<== encodeStructure()");
	}

   // OutputStream methods implementation
   // .......................................................................

	/**
	 * Writes the specified byte to this output stream. The general contract for
	 * <tt>write()</tt> is that one byte is written to the output stream. The
	 * byte to be written is the eight low-order bits of the argument <tt>b</tt>.
	 * The 24 high-order bits of <tt?b</tt> are ignored.
     *
     * @param b the <tt>byte</tt>.
     * @exception IOException if an I/O error occurs. In particular, an
     * <tt>IOException</tt> may be thrown if the output stream has been closed.
     */
	public void write(int b) throws IOException {
		out.write(b & 0xFF);
	}

	/**
	 * Closes the underlying output stream and releases any system resources
	 * associated with it.
	 *
	 * @exception IOException if an I/O error occurs.
	 */
	public void close() throws IOException {
		if (out != null) {
			try {
				out.close();
			} catch (IOException ignored) {
				cat.warn("I/O exception while closing the stream: "+ignored.getMessage());
			}
			out = null;
		}
	}

	/**
	 * Flushes this output stream and forces any buffered output bytes to be
	 * written out. The general contract of <tt>flush()</tt> is that calling it is
	 * an indication that, if any bytes previously written have been buffered by
	 * the implementation of the output stream, such bytes should immediately be
	 * written to their intended destination.
	 *
	 * @exception IOException if an I/O error occurs.
	 */
	public void flush() throws IOException {
		out.flush();
	}

	// Tag-related methods
	// .......................................................................

    /**
     * Outputs the current value of this <tt>Tag</tt> instance to the
     * designated output stream.
     *
     * @param tag the Tag instance.
	 * @exception IOException if an exception occurs while executing this method.
     */
	private void encode(Tag tag) throws IOException {
        int t = tag.getClazz();
        if (tag.isConstructed())
            t |= 0x20;
        int value = tag.getValue();
        if (value < 0x1F)
            write(t | value);
        else {
            write(t | 0x1F);
            t = value;
            while (t > 63) {
                write(63);
                t -= 63;
            }
            write(t);
        }
    }

	// Length-related methods
	// .......................................................................

	/**
	 * Encodes the length element of a DER triplet.
	 *
	 * @param length the size in bytes of a DER value.
	 * @exception IOException if an exception occurs while executing this method.
	 */
	private void encode(int length) throws IOException {
		if (length < 128) { // short definite form
			write(length);
			return;
		}
		if (length < 256) { // long definite form
			write(-127);
			write(length);
			return;
		}
		if (length < 65536) {
			write(-126);
			write(length >> 8);
			write(length);
			return;
		}
		if (length < 16777216) {
			write(-125);
			write(length >> 16);
			write(length >>  8);
			write(length);
			return;
		}
		write(-124);
		write(length >> 24);
		write(length >> 16);
		write(length >>  8);
		write(length);
	}

	// Other instance methods
	// .......................................................................

	/**
	 * Convenience method.<p>
	 *
	 * Returns the byte array containing the proper encoding of the designated
	 * byte array as if tagged by the designated UNIVERSAL class value.
	 *
	 * @param universalValue a UNIVERSAL class value to use for tagging.
	 * @param ba the raw data of an object to encode.
	 * @return the proper TLV (DER triplet) encoding.
	 * @exception IOException if an exception occurs while executing this method.
	 */
	private byte[] toTLV(int universalValue, byte[] ba) throws IOException {
		ByteArrayOutputStream baos = new ByteArrayOutputStream();
		DerEncoder local = new DerEncoder();
		local.open(baos);

		local.encode(new Tag(universalValue));
		local.encode(ba.length);
		local.write(ba);

		local.close();
		return (baos.toByteArray());
	}

   /**
    * Encodes OID subidentifier(s) on 7 bits + 1 bit indicating if last byte or
    * not.<p>
    *
    * <b>BEWARE:</b> This assumes definite length encoding; ie. it will not work
    * if value is too big and needs more than 4 bytes to be encoded.
    *
    * @param baos output stream to write encoding to.
    * @param c if this represents the first 2 subidentifiers, enter value as
    * first * 40 + second, otherwise just call with subidentifier's value.
    * @throws IOException in case we have problems outputting to stream.
    */
   private void encodeSubIdentifier(OutputStream os, int c)
   throws IOException {
      cat.debug("==> encodeSubIdentifier(os, "+String.valueOf(c)+")");

      int i = 0;
      byte[] ab = new byte[4];
      for ( ; i < 4; i++){
         ab[i] = (byte)(c & 0x7F);
         c >>>= 7;
         if (c == 0)
            break;
      }

      // all bytes, except last one have 8th bit set to 1
      for ( ; i > 0; i--)
         os.write((ab[i] | 0x80) & 0xFF);
      os.write(ab[0] & 0xFF);

      cat.debug("<== encodeSubIdentifier()");
   }
}

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?