AndroidKeyStore密钥生成期间{IllegalArgumentException(Unparseable date)

时间:2016-03-14 12:24:58

标签: java android security

我在使用AndroidKeyStore生成RSA密钥期间在我的应用程序中遇到了以下问题,而不是理解它可以在Android SDK的BasicAndroidKeyStore示例应用程序中轻松复制。因此,如果您的Locale.getDefault() == Locale.US比此示例效果良好,但如果您将语言环境更改为"ar_EG",则会因异常而崩溃:

  

java.lang.IllegalArgumentException:无效的日期字符串:Unparseable   日期:" af`cadaaedcaGMT + 00:00" (在偏移0处)                                                                                               在   com.android.org.bouncycastle.asn1.DERUTCTime。(DERUTCTime.java:98)                                                                                               在com.android.org.bouncycastle.asn1.x509.Time。(Time.java:62)                                                                                               在   com.android.org.bouncycastle.x509.X509V3CertificateGenerator.setNotBefore(X509V3CertificateGenerator.java:112)                                                                                               在   android.security.AndroidKeyPairGenerator.generateKeyPair(AndroidKeyPairGenerator.java:127)                                                                                               在   java.security.KeyPairGenerator $ KeyPairGeneratorImpl.generateKeyPair(KeyPairGenerator.java:276)                                                                                               在   com.example.android.basicandroidkeystore.BasicAndroidKeyStoreFragment.createKeys(BasicAndroidKeyStoreFragment.java:237)

因此,问题在于转换为String的密钥有效时间是针对默认语言环境进行的。 以下是ASN1UTCTime类的代码段,在KeyPairGenerator.generateKeyPair()方法调用后引用:

public ASN1UTCTime(
    String time)
{
    this.time = Strings.toByteArray(time);
    try
    {
        this.getDate();
    }
    catch (ParseException e)
    {
        throw new IllegalArgumentException("invalid date string: " + e.getMessage());
    }
}

在调用此方法之前,Date对象将传递给使用默认系统区域设置的以下Time构造函数:

public Time(
        Date    time)
    {
        SimpleTimeZone      tz = new SimpleTimeZone(0, "Z");
        SimpleDateFormat    dateF = new SimpleDateFormat("yyyyMMddHHmmss");
        dateF.setTimeZone(tz);
        String  d = dateF.format(time) + "Z";
        int     year = Integer.parseInt(d.substring(0, 4));
        if (year < 1950 || year > 2049)
        {
            this.time = new DERGeneralizedTime(d);
        }
        else
        {
            this.time = new DERUTCTime(d.substring(2));
        }
    } 

这很奇怪,因为ASN1UTCTime类有另一个构造函数,它似乎更适合国际工作:

/**
     * Base constructor from a java.util.date and Locale - you may need to use this if the default locale
     * doesn't use a Gregorian calender so that the GeneralizedTime produced is compatible with other ASN.1 implementations.
     *
     * @param time a date object representing the time of interest.
     * @param locale an appropriate Locale for producing an ASN.1 UTCTime value.
     */
    public ASN1UTCTime(
        Date time,
        Locale locale)
    {
        SimpleDateFormat dateF = new SimpleDateFormat("yyMMddHHmmss'Z'", locale);
        dateF.setTimeZone(new SimpleTimeZone(0,"Z"));
        this.time = Strings.toByteArray(dateF.format(time));
    } 

那么,什么是正确的解决方案或建议如何解决这个问题?

3 个答案:

答案 0 :(得分:5)

这是known issue with AndroidKeyStore

Android KeyStore没有正确接受语言环境,并且它会导致设备语言环境的失败,语言从右到左。样本堆栈跟踪:

import cv2
import numpy as np

#Created an image (really an ndarray) with three channels 
new_image = np.ndarray((3, num_rows, num_cols), dtype=int)

#Did manipulations for my project where my array values went way over 255
#Eventually returned numbers to between 0 and 255

#Converted the datatype to np.uint8
new_image = new_image.astype(np.uint8)

#Separated the channels in my new image
new_image_red, new_image_green, new_image_blue = new_image

#Stacked the channels
new_rgb = np.dstack([new_image_red, new_image_green, new_image_blue])

#Displayed the image
cv2.imshow("WindowNameHere", new_rgbrgb)
cv2.waitKey(0)

解决方法是在生成密钥对之前设置英语区域设置并将其更改回来:

Caused by: java.lang.IllegalArgumentException: invalid date string: Unparseable date: "aga``eaeeb`eGMT+00:00" (at offset 0)
    at com.android.org.bouncycastle.asn1.DERUTCTime.<init>(DERUTCTime.java:98)
    at com.android.org.bouncycastle.asn1.x509.Time.<init>(Time.java:62)
    at com.android.org.bouncycastle.x509.X509V3CertificateGenerator.setNotBefore(X509V3CertificateGenerator.java:112)
    at android.security.AndroidKeyPairGenerator.generateKeyPair(AndroidKeyPairGenerator.java:128)
    at java.security.KeyPairGenerator$KeyPairGeneratorImpl.generateKeyPair(KeyPairGenerator.java:275)

答案 1 :(得分:0)

我在Android M中使用以下代码生成RSA密钥对。可能会帮助您。

KeyPairGenerator gen = KeyPairGenerator.getInstance("RSA",
                    "AndroidKeyStore");
            gen.initialize(new KeyGenParameterSpec.Builder(KEY_ALIAS,
                    KeyProperties.PURPOSE_ENCRYPT
                            | KeyProperties.PURPOSE_DECRYPT)
                                    .setDigests(KeyProperties.DIGEST_SHA256,
                                            KeyProperties.DIGEST_SHA512)
                                    .setSignaturePaddings(
                                            KeyProperties.SIGNATURE_PADDING_RSA_PSS)
                                    .setEncryptionPaddings(
                                            KeyProperties.ENCRYPTION_PADDING_RSA_OAEP)
                                    .build());

            KeyPair keyPair = gen.generateKeyPair();

答案 2 :(得分:0)

1- 将计算机的日期和时间设置为默认设置
2- 为您所在地区设置正确的时区
3- 重启安卓工作室