int bits = ilength * iw; // number of all used bits byte[] out = new byte[(bits+ow-1)/ow]; // starting from the 0th bit in the input int ipos = 0; // the number of padding 0's needed in the output, skip them int opos = (bits+ow-1)/ow*ow-bits; while(ipos < bits) { int count = iw - ipos%iw; // unpacked bits in current input byte if (count > ow - opos%ow) { // free space available in output byte count = ow - opos%ow; // choose the smaller number } // and move them! out[opos/ow] |= // paste! (((in[ioffset+ipos/iw]+256) // locate the byte (+256 so that it's never negative) >> (iw-ipos%iw-count)) // move to the end of a byte & ((1 << (count))-1)) // zero out all other bits << (ow-opos%ow-count); // move to the output position ipos += count; // advance opos += count; // advance } return out; } /** * Repack from NUB 8 to a NUB 7 OID sub-identifier, remove all * unnecessary 0 headings, set the first bit of all non-tail * output bytes to 1 (as ITU-T Rec. X.690 8.19.2 says), and * paste it into an existing byte array. * @param out the existing array to be pasted into * @param ooffset the starting position to paste * @return the number of bytes pasted */ private static int pack7Oid(byte[] in, int ioffset, int ilength, byte[] out, int ooffset) { byte[] pack = pack(in, ioffset, ilength, 8, 7); int firstNonZero = pack.length-1; // paste at least one byte for (int i=pack.length-2; i>=0; i--) { if (pack[i] != 0) { firstNonZero = i; } pack[i] |= 0x80; } System.arraycopy(pack, firstNonZero, out, ooffset, pack.length-firstNonZero); return pack.length-firstNonZero; } /** * Repack from NUB 7 to NUB 8, remove all unnecessary 0 * headings, and paste it into an existing byte array. * @param out the existing array to be pasted into * @param ooffset the starting position to paste * @return the number of bytes pasted */ private static int pack8(byte[] in, int ioffset, int ilength, byte[] out, int ooffset) { byte[] pack = pack(in, ioffset, ilength, 7, 8); int firstNonZero = pack.length-1; // paste at least one byte for (int i=pack.length-2; i>=0; i--) { if (pack[i] != 0) { firstNonZero = i; } } System.arraycopy(pack, firstNonZero, out, ooffset, pack.length-firstNonZero); return pack.length-firstNonZero; } /** * Pack the int into a OID sub-identifier DER encoding */ private static int pack7Oid(int input, byte[] out, int ooffset) { byte[] b = new byte[4]; b[0] = (byte)(input >> 24); b[1] = (byte)(input >> 16); b[2] = (byte)(input >> 8); b[3] = (byte)(input); return pack7Oid(b, 0, 4, out, ooffset); } /** * Pack the BigInteger into a OID subidentifier DER encoding */ private static int pack7Oid(BigInteger input, byte[] out, int ooffset) { byte[] b = input.toByteArray(); return pack7Oid(b, 0, b.length, out, ooffset); } /** * Private methods to check validity of OID. They must be -- * 1. at least 2 components * 2. all components must be non-negative * 3. the first must be 0, 1 or 2 * 4. if the first is 0 or 1, the second must be <40 */ /** * Check the DER encoding. Since DER encoding defines that the integer bits * are unsigned, so there's no need to check the MSB. */ private static void check(byte[] encoding) throws IOException { int length = encoding.length; if (length < 1 || // too short (encoding[length - 1] & 0x80) != 0) { // not ended throw new IOException("ObjectIdentifier() -- " + "Invalid DER encoding, not ended"); } for (int i=0; i<length; i++) { // 0x80 at the beginning of a subidentifier if (encoding[i] == (byte)0x80 && (i==0 || (encoding[i-1] & 0x80) == 0)) { throw new IOException("ObjectIdentifier() -- " + "Invalid DER encoding, useless extra octet detected"); } } } private static void checkCount(int count) throws IOException { if (count < 2) { throw new IOException("ObjectIdentifier() -- " + "Must be at least two oid components "); } } private static void checkFirstComponent(int first) throws IOException { if (first < 0 || first > 2) { throw new IOException("ObjectIdentifier() -- " + "First oid component is invalid "); } } private static void checkFirstComponent(BigInteger first) throws IOException { if (first.signum() == -1 || first.compareTo(BigInteger.valueOf(2)) == 1) { throw new IOException("ObjectIdentifier() -- " + "First oid component is invalid "); } } private static void checkSecondComponent(int first, int second) throws IOException { if (second < 0 || first != 2 && second > 39) { throw new IOException("ObjectIdentifier() -- " + "Second oid component is invalid "); } } private static void checkSecondComponent(int first, BigInteger second) throws IOException { if (second.signum() == -1 || first != 2 && second.compareTo(BigInteger.valueOf(39)) == 1) { throw new IOException("ObjectIdentifier() -- " + "Second oid component is invalid "); } } private static void checkOtherComponent(int i, int num) throws IOException { if (num < 0) { throw new IOException("ObjectIdentifier() -- " + "oid component #" + (i+1) + " must be non-negative "); } } private static void checkOtherComponent(int i, BigInteger num) throws IOException { if (num.signum() == -1) { throw new IOException("ObjectIdentifier() -- " + "oid component #" + (i+1) + " must be non-negative "); } }}Lines 501–662 of 662. Previous lines
int bits = ilength * iw; // number of all used bits byte[] out = new byte[(bits+ow-1)/ow]; // starting from the 0th bit in the input int ipos = 0; // the number of padding 0's needed in the output, skip them int opos = (bits+ow-1)/ow*ow-bits; while(ipos < bits) { int count = iw - ipos%iw; // unpacked bits in current input byte if (count > ow - opos%ow) { // free space available in output byte count = ow - opos%ow; // choose the smaller number } // and move them! out[opos/ow] |= // paste! (((in[ioffset+ipos/iw]+256) // locate the byte (+256 so that it's never negative) >> (iw-ipos%iw-count)) // move to the end of a byte & ((1 << (count))-1)) // zero out all other bits << (ow-opos%ow-count); // move to the output position ipos += count; // advance opos += count; // advance } return out; } /** * Repack from NUB 8 to a NUB 7 OID sub-identifier, remove all * unnecessary 0 headings, set the first bit of all non-tail * output bytes to 1 (as ITU-T Rec. X.690 8.19.2 says), and * paste it into an existing byte array. * @param out the existing array to be pasted into * @param ooffset the starting position to paste * @return the number of bytes pasted */ private static int pack7Oid(byte[] in, int ioffset, int ilength, byte[] out, int ooffset) { byte[] pack = pack(in, ioffset, ilength, 8, 7); int firstNonZero = pack.length-1; // paste at least one byte for (int i=pack.length-2; i>=0; i--) { if (pack[i] != 0) { firstNonZero = i; } pack[i] |= 0x80; } System.arraycopy(pack, firstNonZero, out, ooffset, pack.length-firstNonZero); return pack.length-firstNonZero; } /** * Repack from NUB 7 to NUB 8, remove all unnecessary 0 * headings, and paste it into an existing byte array. * @param out the existing array to be pasted into * @param ooffset the starting position to paste * @return the number of bytes pasted */ private static int pack8(byte[] in, int ioffset, int ilength, byte[] out, int ooffset) { byte[] pack = pack(in, ioffset, ilength, 7, 8); int firstNonZero = pack.length-1; // paste at least one byte for (int i=pack.length-2; i>=0; i--) { if (pack[i] != 0) { firstNonZero = i; } } System.arraycopy(pack, firstNonZero, out, ooffset, pack.length-firstNonZero); return pack.length-firstNonZero; } /** * Pack the int into a OID sub-identifier DER encoding */ private static int pack7Oid(int input, byte[] out, int ooffset) { byte[] b = new byte[4]; b[0] = (byte)(input >> 24); b[1] = (byte)(input >> 16); b[2] = (byte)(input >> 8); b[3] = (byte)(input); return pack7Oid(b, 0, 4, out, ooffset); } /** * Pack the BigInteger into a OID subidentifier DER encoding */ private static int pack7Oid(BigInteger input, byte[] out, int ooffset) { byte[] b = input.toByteArray(); return pack7Oid(b, 0, b.length, out, ooffset); } /** * Private methods to check validity of OID. They must be -- * 1. at least 2 components * 2. all components must be non-negative * 3. the first must be 0, 1 or 2 * 4. if the first is 0 or 1, the second must be <40 */ /** * Check the DER encoding. Since DER encoding defines that the integer bits * are unsigned, so there's no need to check the MSB. */ private static void check(byte[] encoding) throws IOException { int length = encoding.length; if (length < 1 || // too short (encoding[length - 1] & 0x80) != 0) { // not ended throw new IOException("ObjectIdentifier() -- " + "Invalid DER encoding, not ended"); } for (int i=0; i<length; i++) { // 0x80 at the beginning of a subidentifier if (encoding[i] == (byte)0x80 && (i==0 || (encoding[i-1] & 0x80) == 0)) { throw new IOException("ObjectIdentifier() -- " + "Invalid DER encoding, useless extra octet detected"); } } } private static void checkCount(int count) throws IOException { if (count < 2) { throw new IOException("ObjectIdentifier() -- " + "Must be at least two oid components "); } } private static void checkFirstComponent(int first) throws IOException { if (first < 0 || first > 2) { throw new IOException("ObjectIdentifier() -- " + "First oid component is invalid "); } } private static void checkFirstComponent(BigInteger first) throws IOException { if (first.signum() == -1 || first.compareTo(BigInteger.valueOf(2)) == 1) { throw new IOException("ObjectIdentifier() -- " + "First oid component is invalid "); } } private static void checkSecondComponent(int first, int second) throws IOException { if (second < 0 || first != 2 && second > 39) { throw new IOException("ObjectIdentifier() -- " + "Second oid component is invalid "); } } private static void checkSecondComponent(int first, BigInteger second) throws IOException { if (second.signum() == -1 || first != 2 && second.compareTo(BigInteger.valueOf(39)) == 1) { throw new IOException("ObjectIdentifier() -- " + "Second oid component is invalid "); } } private static void checkOtherComponent(int i, int num) throws IOException { if (num < 0) { throw new IOException("ObjectIdentifier() -- " + "oid component #" + (i+1) + " must be non-negative "); } } private static void checkOtherComponent(int i, BigInteger num) throws IOException { if (num.signum() == -1) { throw new IOException("ObjectIdentifier() -- " + "oid component #" + (i+1) + " must be non-negative "); } } }