0

で開始するActivityと、 KeyManager取得していますjava.lang.NullPointException

public class KeyManager extends Activity implements OnClickListener{
public KeyManager() {
    super();
}

public KeyPair createKeyPair(Context c)
{
    KeyPairGenerator kpg;
    KeyPair kp=null;
    try 
    {
        kpg = KeyPairGenerator.getInstance("RSA");
        kpg.initialize(1024);//1024 bits
        kp = kpg.genKeyPair();

        this.savePrivateKeyInKeyChain(kp, c);
        this.savePublicKeyInSharedPreferences(kp, c);

    } catch (NoSuchAlgorithmException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    } catch (CertificateException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }
    return kp;
}

///////////////////////////////////////
//////////// KEY CHAIN ////////////////
///////////////////////////////////////

public void savePublicKeyInSharedPreferences(KeyPair kp, Context c)
{
    SharedPreferences sharedPreferences = c.getSharedPreferences("Keys", Context.MODE_PRIVATE);
    SharedPreferences.Editor editor = sharedPreferences.edit();

    PublicKey pk=kp.getPublic();
    byte [] pkEncoded=pk.getEncoded();
    Log.i("Public Key", "original encoded:"+pkEncoded);

    String publicKeyString=Base64.encodeToString(pkEncoded,false);
    Log.i("Public Key", "encodeToString:"+publicKeyString);

    editor.putString("public", publicKeyString);

    editor.commit();
}

public static void savePrivateKeyInKeyChain (KeyPair kp, Context c) throws CertificateException
{
    Intent intent = KeyChain.createInstallIntent(); 
    byte [] cert=this.getCertificateForPrivateKey(kp);
    Log.i("CERT",""+cert);
    intent.putExtra(KeyChain.EXTRA_CERTIFICATE, cert);
    intent.putExtra(KeyChain.EXTRA_PKCS12, kp.getPrivate().getEncoded());
    c.startActivity(intent);
}

public static byte [] getCertificateForPrivateKey(KeyPair kp) throws CertificateException
{
    X500Name name=new X500Name("CN=" + "setichat" + ", OU=None, O=None L=None, C=None");
    BigInteger num=new BigInteger("1");
    Date now=new Date(System.currentTimeMillis() - 1000L * 60 * 60 * 24 * 30);
    Date after=new Date(System.currentTimeMillis() + (1000L * 60 * 60 * 24 * 365*10));
    PublicKey pubk=kp.getPublic();
    PrivateKey prik = kp.getPrivate();

    X509v3CertificateBuilder builder= new X509v3CertificateBuilder(name, num, now, after, name, SubjectPublicKeyInfo.getInstance(pubk.getEncoded()));
    byte[] certBytes=null;

    try 
    {
        certBytes = builder.build(new JCESigner(prik,"SHA256withRSA")).getEncoded();

    } catch (IOException e) 
    {
        e.printStackTrace();
    }

    CertificateFactory certificateFactory = CertificateFactory.getInstance("X.509");
    X509Certificate certificate = (X509Certificate) certificateFactory.generateCertificate(new ByteArrayInputStream(certBytes));

    return certificate.getEncoded();
}

public void saveAliasInSharedPreferences(String alias)
{
    SharedPreferences sharedPreferences = getApplicationContext().getSharedPreferences("Alias", Context.MODE_PRIVATE);
    SharedPreferences.Editor editor = sharedPreferences.edit();

    editor.putString("alias", alias);
    Log.i("Alias saved", alias);
    editor.commit();
}

public String getAliasFromSharedPreferences()
{
    SharedPreferences sharedPreferences = getApplicationContext().getSharedPreferences("Alias", Context.MODE_PRIVATE);

    String a=sharedPreferences.getString("alias", null);
    Log.i("Alias get", a);
    return a;
}

public String getPrivateKeyFromAlias()
{
    String alias=getAliasFromSharedPreferences();
    PrivateKey pk=null;
    String result=null;

    try 
    {
        pk = KeyChain.getPrivateKey(getApplicationContext(), alias);
        byte [] pkEncoded=pk.getEncoded();
        result=Base64.encodeToString(pkEncoded,false);
        Log.i("Private Key Alias", "encodeToString:"+result);

    } catch (KeyChainException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    } catch (InterruptedException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }
    return result;
}

   public boolean hasKeys(Context c)
{
    boolean result=false;
    SharedPreferences sharedPreferences = c.getSharedPreferences("Alias", Context.MODE_PRIVATE);
    String p=sharedPreferences.getString("alias", null);
    if(p!=null)
        result=true;

    return result;
}


@Override
public void onClick(DialogInterface arg0, int arg1) {
    // TODO Auto-generated method stub
    KeyChain.choosePrivateKeyAlias(this,
            new KeyChainAliasCallback() {
                public void alias(String alias) {
                //Remember the alias selection for future use.
                if (alias != null) saveAliasInSharedPreferences(alias);
                }
            },
            null, // List of acceptable key types. null for any
            null, // issuer, null for any
            null, // host name of server requesting the cert, null if unavailable
            -1, // port of server requesting the cert, -1 if unavailable
            null); // alias to preselect, null if unavailable
}

public X509Certificate[] getCertificateFromAlias(String alias) throws KeyChainException, InterruptedException
{
    X509Certificate[] chain= KeyChain.getCertificateChain(getApplicationContext(), alias);
    return chain;
}
 }

class JCESigner implements ContentSigner {

private static final AlgorithmIdentifier PKCS1_SHA256_WITH_RSA_OID = new AlgorithmIdentifier(new ASN1ObjectIdentifier("1.2.840.113549.1.1.11"));

private Signature signature;
private ByteArrayOutputStream outputStream;

public JCESigner(PrivateKey privateKey, String signatureAlgorithm) {
    if (!"SHA256withRSA".equals(signatureAlgorithm)) {
        throw new IllegalArgumentException("Signature algorithm \"" + signatureAlgorithm + "\" not yet supported");
    }
    try {
        this.outputStream = new ByteArrayOutputStream();
        this.signature = Signature.getInstance(signatureAlgorithm);
        this.signature.initSign(privateKey);
    } catch (GeneralSecurityException gse) {
        throw new IllegalArgumentException(gse.getMessage());
    }
}

@Override
public AlgorithmIdentifier getAlgorithmIdentifier() {
    if (signature.getAlgorithm().equals("SHA256withRSA")) {
        return PKCS1_SHA256_WITH_RSA_OID;
    } else {
        return null;
    }
}

@Override
public OutputStream getOutputStream() {
    return outputStream;
}

@Override
public byte[] getSignature() {
    try {
        signature.update(outputStream.toByteArray());
        return signature.sign();
    } catch (GeneralSecurityException gse) {
        gse.printStackTrace();
        return null;
    }
}

KeyChain.createInstallIntent()返される値は次のとおりです。

04-21 18:31:41.054: I/Intent(1645): Intent { act=android.credentials.INSTALL cmp=com.android.certinstaller/.CertInstallerMain }

SettingsFragment.onListItemClick のコードは次のとおりです。

@Override
public void onListItemClick(ListView l, View v, int position, long id) {

    CheckedTextView textview = (CheckedTextView)v;
    textview.setChecked(!textview.isChecked());

    if(position==0)
    {
        if(textview.isChecked())
        {
            encrypted=true;
            System.out.println("Encrypted true");
        }
        else
        {   
            encrypted=false;
            System.out.println("Encrypted false");
        }
    }
    else if(position==1)
    {

        if(textview.isChecked())
        {
            signed=true;
            System.out.println("Signed True");

            if(!KeyManager.hasKeys(l.getContext())){
                KeyManager.createKeyPair(l.getContext());
                SeTIKeyUpload upload = new SeTIKeyUpload();
                String setiUpload = upload.keyUploadString(l.getContext());
                SeTIChatService mService = SeTIChatServiceBinder.getService();
                mService.sendMessage(setiUpload);
            }
        }
        else
        {
            signed=false;
            System.out.println("Signed False");
        }   
    }
    System.out.println(position+"position"+", encrypted: "+encrypted+", signed: "+signed);
    SharedPreferences sharedPreferences = v.getContext().getSharedPreferences("Settings", MODE_PRIVATE);
    SharedPreferences.Editor editor = sharedPreferences.edit();
    editor.putBoolean("encrypted", encrypted);
    editor.putBoolean("signed", signed);
    editor.commit();
}

Certificate と PKCS12 が空でないことを確認したので、Intent は空ではありません。

エラーコンソール:

04-21 17:17:31.524: E/AndroidRuntime(927): FATAL EXCEPTION: main
04-21 17:17:31.524: E/AndroidRuntime(927): java.lang.NullPointerException
04-21 17:17:31.524: E/AndroidRuntime(927):  at android.app.Activity.startActivityForResult(Activity.java:3370)
04-21 17:17:31.524: E/AndroidRuntime(927):  at android.app.Activity.startActivityForResult(Activity.java:3331)
04-21 17:17:31.524: E/AndroidRuntime(927):  at android.app.Activity.startActivity(Activity.java:3566)
04-21 17:17:31.524: E/AndroidRuntime(927):  at android.app.Activity.startActivity(Activity.java:3534)
04-21 17:17:31.524: E/AndroidRuntime(927):  at es.uc3m.setichat.utils.KeyManager.savePrivateKeyInKeyChain(KeyManager.java:288)
04-21 17:17:31.524: E/AndroidRuntime(927):  at es.uc3m.setichat.utils.KeyManager.createKeyPair(KeyManager.java:188)
04-21 17:17:31.524: E/AndroidRuntime(927):  at es.uc3m.setichat.activity.SettingsFragment.onListItemClick(SettingsFragment.java:102)
04-21 17:17:31.524: E/AndroidRuntime(927):  at android.app.ListFragment$2.onItemClick(ListFragment.java:160)
04-21 17:17:31.524: E/AndroidRuntime(927):  at android.widget.AdapterView.performItemClick(AdapterView.java:298)
04-21 17:17:31.524: E/AndroidRuntime(927):  at android.widget.AbsListView.performItemClick(AbsListView.java:1100)
04-21 17:17:31.524: E/AndroidRuntime(927):  at android.widget.AbsListView$PerformClick.run(AbsListView.java:2749)
04-21 17:17:31.524: E/AndroidRuntime(927):  at android.widget.AbsListView$1.run(AbsListView.java:3423)
04-21 17:17:31.524: E/AndroidRuntime(927):  at android.os.Handler.handleCallback(Handler.java:725)
04-21 17:17:31.524: E/AndroidRuntime(927):  at android.os.Handler.dispatchMessage(Handler.java:92)
04-21 17:17:31.524: E/AndroidRuntime(927):  at android.os.Looper.loop(Looper.java:137)
04-21 17:17:31.524: E/AndroidRuntime(927):  at android.app.ActivityThread.main(ActivityThread.java:5039)
04-21 17:17:31.524: E/AndroidRuntime(927):  at java.lang.reflect.Method.invokeNative(Native Method)
04-21 17:17:31.524: E/AndroidRuntime(927):  at java.lang.reflect.Method.invoke(Method.java:511)
04-21 17:17:31.524: E/AndroidRuntime(927):  at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:793)
04-21 17:17:31.524: E/AndroidRuntime(927):  at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:560)
04-21 17:17:31.524: E/AndroidRuntime(927):  at dalvik.system.NativeStart.main(Native Method)

そして、次のように AndroidManifest でクラスを定義しました。

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="es.uc3m.setichat"
    android:versionCode="1"
    android:versionName="1.0" >

    <uses-sdk
        android:minSdkVersion="15"
        android:targetSdkVersion="17" />

    <uses-permission android:name="android.permission.INTERNET" />
    <uses-permission android:name="android.permission.READ_CONTACTS"/>

    <application
        android:allowBackup="true"
        android:icon="@drawable/setichat_icon"
        android:label="@string/app_name"
        android:theme="@style/AppTheme" >
       .
       .
       .
        <activity android:name=".utils.KeyManager"></activity>
    </application>

</manifest>

編集

インテントを起動できるようになりましたが、アプリケーションは「証明書の抽出」ウィンドウでパスワードを要求し、証明書の作成時にパスワードを設定していません。それに関するヒントはありますか?

KeyStore で保存しようとしましたが、パスワードを入力しても違いはありません。

KeyStore ks = KeyStore.getInstance("BKS");
char [] password={'P', 'A', 'S', 'S'};
ks.load(new ByteArrayInputStream(certBytes), password);
ks.setKeyEntry("hostname", kp.getPrivate(), password, new java.security.cert.Certificate[] { certificate });
File keystore = new File("keystore");
FileOutputStream fos = new FileOutputStream(keystore);
ks.store(fos, password);
fos.close();
4

1 に答える 1

1

が実行された時点でアクティビティ コンテキストが失われている可能性がありますsavePrivateKeyInKeyChain()。あなたの関数は、バックグラウンド スレッドからのコールバックを介して実行されているか、アクティビティのライフサイクルがそのコンテキストを準備する前に実行されていると思います。

getContext()その関数の結果をデバッグすることで、そうであるかどうかを簡単に確認できます。を与えている場合はnull、問題があります。

于 2013-04-21T18:09:28.057 に答える