1b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallampackage org.bouncycastle.asn1; 2b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam 3b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallamimport java.io.IOException; 4b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallamimport java.text.ParseException; 5b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallamimport java.text.SimpleDateFormat; 6b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallamimport java.util.Date; 7b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallamimport java.util.SimpleTimeZone; 8c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstromimport java.util.TimeZone; 9b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam 104c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstromimport org.bouncycastle.util.Arrays; 114c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstromimport org.bouncycastle.util.Strings; 124c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom 13b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam/** 14b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam * Generalized time object. 15b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam */ 16b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallampublic class DERGeneralizedTime 174c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom extends ASN1Primitive 18b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam{ 194c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom private byte[] time; 20b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam 21b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam /** 22b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam * return a generalized time from the passed in object 23b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam * 24b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam * @exception IllegalArgumentException if the object cannot be converted. 25b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam */ 264c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom public static ASN1GeneralizedTime getInstance( 27b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam Object obj) 28b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam { 294c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom if (obj == null || obj instanceof ASN1GeneralizedTime) 304c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom { 314c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom return (ASN1GeneralizedTime)obj; 324c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom } 334c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom 344c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom if (obj instanceof DERGeneralizedTime) 35b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam { 364c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom return new ASN1GeneralizedTime(((DERGeneralizedTime)obj).time); 37b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam } 38b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam 3970c8287138e69a98c2f950036f9f703ee37228c8Brian Carlstrom if (obj instanceof byte[]) 4070c8287138e69a98c2f950036f9f703ee37228c8Brian Carlstrom { 4170c8287138e69a98c2f950036f9f703ee37228c8Brian Carlstrom try 4270c8287138e69a98c2f950036f9f703ee37228c8Brian Carlstrom { 4370c8287138e69a98c2f950036f9f703ee37228c8Brian Carlstrom return (ASN1GeneralizedTime)fromByteArray((byte[])obj); 4470c8287138e69a98c2f950036f9f703ee37228c8Brian Carlstrom } 4570c8287138e69a98c2f950036f9f703ee37228c8Brian Carlstrom catch (Exception e) 4670c8287138e69a98c2f950036f9f703ee37228c8Brian Carlstrom { 4770c8287138e69a98c2f950036f9f703ee37228c8Brian Carlstrom throw new IllegalArgumentException("encoding error in getInstance: " + e.toString()); 4870c8287138e69a98c2f950036f9f703ee37228c8Brian Carlstrom } 4970c8287138e69a98c2f950036f9f703ee37228c8Brian Carlstrom } 5070c8287138e69a98c2f950036f9f703ee37228c8Brian Carlstrom 51b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam throw new IllegalArgumentException("illegal object in getInstance: " + obj.getClass().getName()); 52b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam } 53b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam 54b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam /** 55b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam * return a Generalized Time object from a tagged object. 56b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam * 57b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam * @param obj the tagged object holding the object we want 58b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam * @param explicit true if the object is meant to be explicitly 59b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam * tagged false otherwise. 60b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam * @exception IllegalArgumentException if the tagged object cannot 61b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam * be converted. 62b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam */ 634c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom public static ASN1GeneralizedTime getInstance( 64b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam ASN1TaggedObject obj, 65b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam boolean explicit) 66b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam { 674c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom ASN1Primitive o = obj.getObject(); 686e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom 696e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom if (explicit || o instanceof DERGeneralizedTime) 706e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom { 716e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom return getInstance(o); 726e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom } 736e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom else 746e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom { 754c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom return new ASN1GeneralizedTime(((ASN1OctetString)o).getOctets()); 766e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom } 77b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam } 78b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam 79b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam /** 80c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom * The correct format for this is YYYYMMDDHHMMSS[.f]Z, or without the Z 81b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam * for local time, or Z+-HHMM on the end, for difference between local 82c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom * time and UTC time. The fractional second amount f must consist of at 83c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom * least one number with trailing zeroes removed. 84b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam * 85b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam * @param time the time string. 86c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom * @exception IllegalArgumentException if String is an illegal format. 87b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam */ 88b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam public DERGeneralizedTime( 89b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam String time) 90b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam { 914c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom this.time = Strings.toByteArray(time); 92c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom try 93c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom { 94c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom this.getDate(); 95c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom } 96c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom catch (ParseException e) 97c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom { 98c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom throw new IllegalArgumentException("invalid date string: " + e.getMessage()); 99c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom } 100b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam } 101b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam 102b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam /** 1034c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom * base constructor from a java.util.date object 104b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam */ 105b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam public DERGeneralizedTime( 106b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam Date time) 107b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam { 108b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam SimpleDateFormat dateF = new SimpleDateFormat("yyyyMMddHHmmss'Z'"); 109b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam 110b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam dateF.setTimeZone(new SimpleTimeZone(0,"Z")); 111b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam 1124c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom this.time = Strings.toByteArray(dateF.format(time)); 113b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam } 114b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam 115b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam DERGeneralizedTime( 116b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam byte[] bytes) 117b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam { 1184c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom this.time = bytes; 119b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam } 120b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam 121b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam /** 122c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom * Return the time. 123c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom * @return The time string as it appeared in the encoded object. 124c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom */ 125c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom public String getTimeString() 126c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom { 1274c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom return Strings.fromByteArray(time); 128c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom } 129c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom 130c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom /** 131b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam * return the time - always in the form of 132b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam * YYYYMMDDhhmmssGMT(+hh:mm|-hh:mm). 133b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam * <p> 134b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam * Normally in a certificate we would expect "Z" rather than "GMT", 135b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam * however adding the "GMT" means we can just use: 136b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam * <pre> 137b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam * dateF = new SimpleDateFormat("yyyyMMddHHmmssz"); 138b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam * </pre> 139b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam * To read in the time and get a date which is compatible with our local 140b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam * time zone. 141b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam */ 142b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam public String getTime() 143b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam { 1444c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom String stime = Strings.fromByteArray(time); 1454c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom 146b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam // 147b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam // standardise the format. 148b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam // 1494c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom if (stime.charAt(stime.length() - 1) == 'Z') 150b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam { 1514c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom return stime.substring(0, stime.length() - 1) + "GMT+00:00"; 152b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam } 153b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam else 154b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam { 1554c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom int signPos = stime.length() - 5; 1564c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom char sign = stime.charAt(signPos); 157b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam if (sign == '-' || sign == '+') 158b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam { 1594c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom return stime.substring(0, signPos) 160b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam + "GMT" 1614c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom + stime.substring(signPos, signPos + 3) 162b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam + ":" 1634c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom + stime.substring(signPos + 3); 164b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam } 165b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam else 166b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam { 1674c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom signPos = stime.length() - 3; 1684c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom sign = stime.charAt(signPos); 169b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam if (sign == '-' || sign == '+') 170b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam { 1714c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom return stime.substring(0, signPos) 172b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam + "GMT" 1734c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom + stime.substring(signPos) 174b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam + ":00"; 175b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam } 176b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam } 177b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam } 1784c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom return stime + calculateGMTOffset(); 179c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom } 180b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam 181c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom private String calculateGMTOffset() 182c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom { 183c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom String sign = "+"; 184c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom TimeZone timeZone = TimeZone.getDefault(); 185c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom int offset = timeZone.getRawOffset(); 186c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom if (offset < 0) 187c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom { 188c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom sign = "-"; 189c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom offset = -offset; 190c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom } 191c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom int hours = offset / (60 * 60 * 1000); 192c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom int minutes = (offset - (hours * 60 * 60 * 1000)) / (60 * 1000); 193c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom 194c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom try 195c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom { 196c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom if (timeZone.useDaylightTime() && timeZone.inDaylightTime(this.getDate())) 197c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom { 198c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom hours += sign.equals("+") ? 1 : -1; 199c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom } 200c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom } 201c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom catch (ParseException e) 202c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom { 203c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom // we'll do our best and ignore daylight savings 204c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom } 205c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom 206c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom return "GMT" + sign + convert(hours) + ":" + convert(minutes); 207c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom } 208c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom 209c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom private String convert(int time) 210c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom { 211c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom if (time < 10) 212c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom { 213c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom return "0" + time; 214c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom } 215c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom 216c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom return Integer.toString(time); 217b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam } 218b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam 219c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom public Date getDate() 220b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam throws ParseException 221b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam { 222b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam SimpleDateFormat dateF; 2234c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom String stime = Strings.fromByteArray(time); 2244c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom String d = stime; 225b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam 2264c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom if (stime.endsWith("Z")) 227b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam { 228c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom if (hasFractionalSeconds()) 229c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom { 230c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom dateF = new SimpleDateFormat("yyyyMMddHHmmss.SSS'Z'"); 231c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom } 232c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom else 233c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom { 234c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom dateF = new SimpleDateFormat("yyyyMMddHHmmss'Z'"); 235c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom } 236c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom 237c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom dateF.setTimeZone(new SimpleTimeZone(0, "Z")); 238c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom } 2394c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom else if (stime.indexOf('-') > 0 || stime.indexOf('+') > 0) 240c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom { 241c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom d = this.getTime(); 242c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom if (hasFractionalSeconds()) 2436e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom { 244c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom dateF = new SimpleDateFormat("yyyyMMddHHmmss.SSSz"); 245c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom } 246c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom else 247c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom { 248c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom dateF = new SimpleDateFormat("yyyyMMddHHmmssz"); 249c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom } 250c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom 251c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom dateF.setTimeZone(new SimpleTimeZone(0, "Z")); 252b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam } 253b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam else 254b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam { 255c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom if (hasFractionalSeconds()) 256c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom { 257c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom dateF = new SimpleDateFormat("yyyyMMddHHmmss.SSS"); 258c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom } 259c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom else 260c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom { 261c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom dateF = new SimpleDateFormat("yyyyMMddHHmmss"); 262c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom } 263c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom 264c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom dateF.setTimeZone(new SimpleTimeZone(0, TimeZone.getDefault().getID())); 265c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom } 266c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom 267c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom if (hasFractionalSeconds()) 268c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom { 269c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom // java misinterprets extra digits as being milliseconds... 270c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom String frac = d.substring(14); 271c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom int index; 272c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom for (index = 1; index < frac.length(); index++) 273c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom { 274c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom char ch = frac.charAt(index); 275c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom if (!('0' <= ch && ch <= '9')) 276c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom { 277c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom break; 278c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom } 279c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom } 2806e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom 281c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom if (index - 1 > 3) 282c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom { 283c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom frac = frac.substring(0, 4) + frac.substring(index); 284c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom d = d.substring(0, 14) + frac; 285c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom } 2866e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom else if (index - 1 == 1) 2876e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom { 2886e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom frac = frac.substring(0, index) + "00" + frac.substring(index); 2896e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom d = d.substring(0, 14) + frac; 2906e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom } 2916e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom else if (index - 1 == 2) 2926e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom { 2936e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom frac = frac.substring(0, index) + "0" + frac.substring(index); 2946e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom d = d.substring(0, 14) + frac; 2956e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom } 296b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam } 297c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom 298c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom return dateF.parse(d); 299b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam } 300c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom 301c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom private boolean hasFractionalSeconds() 302c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom { 3034c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom for (int i = 0; i != time.length; i++) 3044c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom { 3054c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom if (time[i] == '.') 3064c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom { 3074c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom if (i == 14) 3084c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom { 3094c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom return true; 3104c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom } 3114c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom } 3124c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom } 3134c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom return false; 314c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom } 315c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom 3164c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom boolean isConstructed() 317b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam { 3184c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom return false; 3194c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom } 320b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam 3214c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom int encodedLength() 3224c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom { 3234c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom int length = time.length; 324b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam 3254c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom return 1 + StreamUtil.calculateBodyLength(length) + length; 326b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam } 327b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam 328b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam void encode( 3294c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom ASN1OutputStream out) 330b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam throws IOException 331b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam { 3324c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom out.writeEncoded(BERTags.GENERALIZED_TIME, time); 333b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam } 334b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam 335c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom boolean asn1Equals( 3364c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom ASN1Primitive o) 337b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam { 338c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom if (!(o instanceof DERGeneralizedTime)) 339b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam { 340b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam return false; 341b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam } 342b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam 3434c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom return Arrays.areEqual(time, ((DERGeneralizedTime)o).time); 344b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam } 345b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam 346b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam public int hashCode() 347b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam { 3484c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom return Arrays.hashCode(time); 349b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam } 350b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam} 351