mirror of
https://github.com/square/okhttp.git
synced 2026-01-14 07:22:20 +03:00
Implement DER constraints on date formats (#6213)
The time zone must be 'Z', and cannot be an offset like '+0000'. That is allowed by ASN.1 but not by DER. Closes: https://github.com/square/okhttp/issues/6210
This commit is contained in:
@@ -164,7 +164,7 @@ internal object Adapters {
|
|||||||
|
|
||||||
internal fun parseUtcTime(string: String): Long {
|
internal fun parseUtcTime(string: String): Long {
|
||||||
val utc = TimeZone.getTimeZone("GMT")
|
val utc = TimeZone.getTimeZone("GMT")
|
||||||
val dateFormat = SimpleDateFormat("yyMMddHHmmssXX").apply {
|
val dateFormat = SimpleDateFormat("yyMMddHHmmss'Z'").apply {
|
||||||
timeZone = utc
|
timeZone = utc
|
||||||
set2DigitYearStart(Date(-631152000000L)) // 1950-01-01T00:00:00Z.
|
set2DigitYearStart(Date(-631152000000L)) // 1950-01-01T00:00:00Z.
|
||||||
}
|
}
|
||||||
@@ -179,7 +179,7 @@ internal object Adapters {
|
|||||||
|
|
||||||
internal fun formatUtcTime(date: Long): String {
|
internal fun formatUtcTime(date: Long): String {
|
||||||
val utc = TimeZone.getTimeZone("GMT")
|
val utc = TimeZone.getTimeZone("GMT")
|
||||||
val dateFormat = SimpleDateFormat("yyMMddHHmmssXX").apply {
|
val dateFormat = SimpleDateFormat("yyMMddHHmmss'Z'").apply {
|
||||||
timeZone = utc
|
timeZone = utc
|
||||||
set2DigitYearStart(Date(-631152000000L)) // 1950-01-01T00:00:00Z.
|
set2DigitYearStart(Date(-631152000000L)) // 1950-01-01T00:00:00Z.
|
||||||
}
|
}
|
||||||
@@ -234,7 +234,7 @@ internal object Adapters {
|
|||||||
|
|
||||||
internal fun parseGeneralizedTime(string: String): Long {
|
internal fun parseGeneralizedTime(string: String): Long {
|
||||||
val utc = TimeZone.getTimeZone("GMT")
|
val utc = TimeZone.getTimeZone("GMT")
|
||||||
val dateFormat = SimpleDateFormat("yyyyMMddHHmmssXX").apply {
|
val dateFormat = SimpleDateFormat("yyyyMMddHHmmss'Z'").apply {
|
||||||
timeZone = utc
|
timeZone = utc
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -248,7 +248,7 @@ internal object Adapters {
|
|||||||
|
|
||||||
internal fun formatGeneralizedTime(date: Long): String {
|
internal fun formatGeneralizedTime(date: Long): String {
|
||||||
val utc = TimeZone.getTimeZone("GMT")
|
val utc = TimeZone.getTimeZone("GMT")
|
||||||
val dateFormat = SimpleDateFormat("yyyyMMddHHmmssXX").apply {
|
val dateFormat = SimpleDateFormat("yyyyMMddHHmmss'Z'").apply {
|
||||||
timeZone = utc
|
timeZone = utc
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -33,6 +33,7 @@ import okio.ByteString.Companion.encodeUtf8
|
|||||||
import okio.ByteString.Companion.toByteString
|
import okio.ByteString.Companion.toByteString
|
||||||
import org.assertj.core.api.Assertions.assertThat
|
import org.assertj.core.api.Assertions.assertThat
|
||||||
import org.junit.Assert.fail
|
import org.junit.Assert.fail
|
||||||
|
import org.junit.Ignore
|
||||||
import org.junit.Test
|
import org.junit.Test
|
||||||
|
|
||||||
internal class DerTest {
|
internal class DerTest {
|
||||||
@@ -627,9 +628,13 @@ internal class DerTest {
|
|||||||
assertThat(Adapters.PRINTABLE_STRING.toDer("hi")).isEqualTo(bytes)
|
assertThat(Adapters.PRINTABLE_STRING.toDer("hi")).isEqualTo(bytes)
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test fun `decode utc time with offset`() {
|
@Test fun `cannot decode utc time with offset`() {
|
||||||
val time = Adapters.UTC_TIME.fromDer("17113139313231353139303231302d30383030".decodeHex())
|
try {
|
||||||
assertThat(time).isEqualTo(date("2019-12-16T03:02:10.000+0000").time)
|
Adapters.UTC_TIME.fromDer("17113139313231353139303231302d30383030".decodeHex())
|
||||||
|
fail()
|
||||||
|
} catch (expected: ProtocolException) {
|
||||||
|
assertThat(expected).hasMessage("Failed to parse UTCTime 191215190210-0800")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test fun `utc time`() {
|
@Test fun `utc time`() {
|
||||||
@@ -649,10 +654,13 @@ internal class DerTest {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test fun `decode generalized time with offset`() {
|
@Test fun `cannot decode generalized time with offset`() {
|
||||||
val time = Adapters.GENERALIZED_TIME
|
try {
|
||||||
.fromDer("181332303139313231353139303231302d30383030".decodeHex())
|
Adapters.GENERALIZED_TIME.fromDer("181332303139313231353139303231302d30383030".decodeHex())
|
||||||
assertThat(time).isEqualTo(date("2019-12-16T03:02:10.000+0000").time)
|
fail()
|
||||||
|
} catch (expected: ProtocolException) {
|
||||||
|
assertThat(expected).hasMessage("Failed to parse GeneralizedTime 20191215190210-0800")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test fun `generalized time`() {
|
@Test fun `generalized time`() {
|
||||||
@@ -672,23 +680,25 @@ internal class DerTest {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test fun `parse utc time`() {
|
||||||
|
assertThat(Adapters.parseUtcTime("920521000000Z"))
|
||||||
|
.isEqualTo(date("1992-05-21T00:00:00.000+0000").time)
|
||||||
|
assertThat(Adapters.parseUtcTime("920622123421Z"))
|
||||||
|
.isEqualTo(date("1992-06-22T12:34:21.000+0000").time)
|
||||||
|
assertThat(Adapters.parseUtcTime("920722132100Z"))
|
||||||
|
.isEqualTo(date("1992-07-22T13:21:00.000+0000").time)
|
||||||
|
}
|
||||||
|
|
||||||
@Test fun `decode utc time two digit year cutoff is 1950`() {
|
@Test fun `decode utc time two digit year cutoff is 1950`() {
|
||||||
assertThat(Adapters.parseUtcTime("500101000000-0000"))
|
assertThat(Adapters.parseUtcTime("500101000000Z"))
|
||||||
.isEqualTo(date("1950-01-01T00:00:00.000+0000").time)
|
.isEqualTo(date("1950-01-01T00:00:00.000+0000").time)
|
||||||
assertThat(Adapters.parseUtcTime("500101000000-0100"))
|
assertThat(Adapters.parseUtcTime("500101010000Z"))
|
||||||
.isEqualTo(date("1950-01-01T01:00:00.000+0000").time)
|
.isEqualTo(date("1950-01-01T01:00:00.000+0000").time)
|
||||||
|
|
||||||
assertThat(Adapters.parseUtcTime("491231235959+0100"))
|
assertThat(Adapters.parseUtcTime("491231225959Z"))
|
||||||
.isEqualTo(date("2049-12-31T22:59:59.000+0000").time)
|
.isEqualTo(date("2049-12-31T22:59:59.000+0000").time)
|
||||||
assertThat(Adapters.parseUtcTime("491231235959-0000"))
|
assertThat(Adapters.parseUtcTime("491231235959Z"))
|
||||||
.isEqualTo(date("2049-12-31T23:59:59.000+0000").time)
|
.isEqualTo(date("2049-12-31T23:59:59.000+0000").time)
|
||||||
|
|
||||||
// Note that time zone offsets aren't honored by Java's two-digit offset boundary! A savvy time
|
|
||||||
// traveler could exploit this to get a certificate that expires 100 years later than expected.
|
|
||||||
assertThat(Adapters.parseUtcTime("500101000000+0100"))
|
|
||||||
.isEqualTo(date("2049-12-31T23:00:00.000+0000").time)
|
|
||||||
assertThat(Adapters.parseUtcTime("491231235959-0100"))
|
|
||||||
.isEqualTo(date("2050-01-01T00:59:59.000+0000").time)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test fun `encode utc time two digit year cutoff is 1950`() {
|
@Test fun `encode utc time two digit year cutoff is 1950`() {
|
||||||
@@ -699,14 +709,24 @@ internal class DerTest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test fun `parse generalized time`() {
|
@Test fun `parse generalized time`() {
|
||||||
assertThat(Adapters.parseGeneralizedTime("18990101000000-0000"))
|
assertThat(Adapters.parseGeneralizedTime("18990101000000Z"))
|
||||||
.isEqualTo(date("1899-01-01T00:00:00.000+0000").time)
|
.isEqualTo(date("1899-01-01T00:00:00.000+0000").time)
|
||||||
assertThat(Adapters.parseGeneralizedTime("19500101000000-0000"))
|
assertThat(Adapters.parseGeneralizedTime("19500101000000Z"))
|
||||||
.isEqualTo(date("1950-01-01T00:00:00.000+0000").time)
|
.isEqualTo(date("1950-01-01T00:00:00.000+0000").time)
|
||||||
assertThat(Adapters.parseGeneralizedTime("20500101000000-0000"))
|
assertThat(Adapters.parseGeneralizedTime("20500101000000Z"))
|
||||||
.isEqualTo(date("2050-01-01T00:00:00.000+0000").time)
|
.isEqualTo(date("2050-01-01T00:00:00.000+0000").time)
|
||||||
assertThat(Adapters.parseGeneralizedTime("20990101000000-0000"))
|
assertThat(Adapters.parseGeneralizedTime("20990101000000Z"))
|
||||||
.isEqualTo(date("2099-01-01T00:00:00.000+0000").time)
|
.isEqualTo(date("2099-01-01T00:00:00.000+0000").time)
|
||||||
|
assertThat(Adapters.parseGeneralizedTime("19920521000000Z"))
|
||||||
|
.isEqualTo(date("1992-05-21T00:00:00.000+0000").time)
|
||||||
|
assertThat(Adapters.parseGeneralizedTime("19920622123421Z"))
|
||||||
|
.isEqualTo(date("1992-06-22T12:34:21.000+0000").time)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Ignore("fractional seconds are not implemented")
|
||||||
|
@Test fun `parse generalized time with fractional seconds`() {
|
||||||
|
assertThat(Adapters.parseGeneralizedTime("19920722132100.3Z"))
|
||||||
|
.isEqualTo(date("1992-07-22T13:21:00.300+0000").time)
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test fun `format generalized time`() {
|
@Test fun `format generalized time`() {
|
||||||
|
|||||||
Reference in New Issue
Block a user