1f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectpackage org.bouncycastle.asn1;
2f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
3f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectimport java.io.IOException;
4f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectimport java.text.SimpleDateFormat;
5f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectimport java.util.Date;
6f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectimport java.util.SimpleTimeZone;
7f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
8f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/**
9f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * UTC time object.
10f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
11f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectpublic class DERUTCTime
12f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    extends DERObject
13f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
14f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    String      time;
15f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
16f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /**
17f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * return an UTC Time from the passed in object.
18f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *
19f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * @exception IllegalArgumentException if the object cannot be converted.
20f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
21f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    public static DERUTCTime getInstance(
22f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        Object  obj)
23f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    {
24f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (obj == null || obj instanceof DERUTCTime)
25f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        {
26f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            return (DERUTCTime)obj;
27f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
28f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
29f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (obj instanceof ASN1OctetString)
30f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        {
31f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            return new DERUTCTime(((ASN1OctetString)obj).getOctets());
32f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
33f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
34f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        throw new IllegalArgumentException("illegal object in getInstance: " + obj.getClass().getName());
35f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
36f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
37f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /**
38f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * return an UTC Time from a tagged object.
39f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *
40f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * @param obj the tagged object holding the object we want
41f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * @param explicit true if the object is meant to be explicitly
42f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *              tagged false otherwise.
43f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * @exception IllegalArgumentException if the tagged object cannot
44f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *               be converted.
45f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
46f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    public static DERUTCTime getInstance(
47f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        ASN1TaggedObject obj,
48f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        boolean          explicit)
49f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    {
50f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return getInstance(obj.getObject());
51f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
52f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
53f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /**
54f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * The correct format for this is YYMMDDHHMMSSZ (it used to be that seconds were
55f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * never encoded. When you're creating one of these objects from scratch, that's
56f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * what you want to use, otherwise we'll try to deal with whatever gets read from
57f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * the input stream... (this is why the input format is different from the getTime()
58f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * method output).
59f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * <p>
60f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *
61f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * @param time the time string.
62f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
63f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    public DERUTCTime(
64f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        String  time)
65f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    {
66f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        this.time = time;
67f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
68f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
69f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /**
70f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * base constructer from a java.util.date object
71f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
72f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    public DERUTCTime(
73f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        Date time)
74f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    {
75f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        SimpleDateFormat dateF = new SimpleDateFormat("yyMMddHHmmss'Z'");
76f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
77f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        dateF.setTimeZone(new SimpleTimeZone(0,"Z"));
78f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
79f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        this.time = dateF.format(time);
80f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
81f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
82f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    DERUTCTime(
83f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        byte[]  bytes)
84f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    {
85f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        //
86f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        // explicitly convert to characters
87f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        //
88f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        char[]  dateC = new char[bytes.length];
89f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
90f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        for (int i = 0; i != dateC.length; i++)
91f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        {
92f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            dateC[i] = (char)(bytes[i] & 0xff);
93f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
94f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
95f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        this.time = new String(dateC);
96f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
97f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
98f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /**
99f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * return the time - always in the form of
100f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *  YYMMDDhhmmssGMT(+hh:mm|-hh:mm).
101f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * <p>
102f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Normally in a certificate we would expect "Z" rather than "GMT",
103f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * however adding the "GMT" means we can just use:
104f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * <pre>
105f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *     dateF = new SimpleDateFormat("yyMMddHHmmssz");
106f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * </pre>
107f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * To read in the time and get a date which is compatible with our local
108f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * time zone.
109f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * <p>
110f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * <b>Note:</b> In some cases, due to the local date processing, this
111f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * may lead to unexpected results. If you want to stick the normal
112f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * convention of 1950 to 2049 use the getAdjustedTime() method.
113f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
114f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    public String getTime()
115f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    {
116f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        //
117f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        // standardise the format.
118f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        //
119f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (time.length() == 11)
120f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        {
121f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            return time.substring(0, 10) + "00GMT+00:00";
122f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
123f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        else if (time.length() == 13)
124f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        {
125f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            return time.substring(0, 12) + "GMT+00:00";
126f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
127f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        else if (time.length() == 17)
128f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        {
129f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            return time.substring(0, 12) + "GMT" + time.substring(12, 15) + ":" + time.substring(15, 17);
130f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
131f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
132f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return time;
133f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
134f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
135f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /**
136f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * return the time as an adjusted date with a 4 digit year. This goes
137f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * in the range of 1950 - 2049.
138f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
139f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    public String getAdjustedTime()
140f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    {
141f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        String   d = this.getTime();
142f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
143f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (d.charAt(0) < '5')
144f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        {
145f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            return "20" + d;
146f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
147f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        else
148f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        {
149f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            return "19" + d;
150f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
151f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
152f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
153f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    private byte[] getOctets()
154f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    {
155f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        char[]  cs = time.toCharArray();
156f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        byte[]  bs = new byte[cs.length];
157f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
158f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        for (int i = 0; i != cs.length; i++)
159f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        {
160f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            bs[i] = (byte)cs[i];
161f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
162f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
163f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return bs;
164f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
165f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
166f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    void encode(
167f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        DEROutputStream  out)
168f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        throws IOException
169f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    {
170f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        out.writeEncoded(UTC_TIME, this.getOctets());
171f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
172f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
173f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    public boolean equals(
174f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        Object  o)
175f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    {
176f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if ((o == null) || !(o instanceof DERUTCTime))
177f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        {
178f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            return false;
179f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
180f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
181f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return time.equals(((DERUTCTime)o).time);
182f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
183f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
184f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    public int hashCode()
185f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    {
186f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return time.hashCode();
187f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
188f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
189f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    public String toString()
190f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    {
191f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project      return time;
192f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
193f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
194