Index: net/android/java/src/org/chromium/net/AndroidKeyStore.java |
diff --git a/net/android/java/src/org/chromium/net/AndroidKeyStore.java b/net/android/java/src/org/chromium/net/AndroidKeyStore.java |
new file mode 100644 |
index 0000000000000000000000000000000000000000..949ba442c76432ab48cf2fb64c197f59fd3bf7f7 |
--- /dev/null |
+++ b/net/android/java/src/org/chromium/net/AndroidKeyStore.java |
@@ -0,0 +1,126 @@ |
+// Copyright (c) 2012 The Chromium Authors. All rights reserved. |
+// Use of this source code is governed by a BSD-style license that can be |
+// found in the LICENSE file. |
+ |
+package org.chromium.net; |
+ |
+import android.util.Log; |
+ |
+import java.security.interfaces.DSAPrivateKey; |
+import java.security.interfaces.ECPrivateKey; |
+import java.security.interfaces.RSAPrivateKey; |
+import java.security.PrivateKey; |
+import java.security.Signature; |
+ |
+import org.chromium.base.CalledByNative; |
+import org.chromium.base.JNINamespace; |
+import org.chromium.net.SSLClientCertType; |
+ |
+@JNINamespace("net::android") |
+public class AndroidKeyStore { |
+ |
+ private static final String TAG = AndroidKeyStore.class.getName(); |
+ |
+ //////////////////////////////////////////////////////////////////// |
+ // |
+ // Message signing support. |
+ // |
+ |
+ /** |
+ * Called from native code to sign a given message with an RSA-based |
+ * PrivateKey object. |
+ * Assumes that initSignatureForKey() was called previously on the |
+ * same privateKey handle. |
+ * @param privateKey The PrivateKey handle. |
+ * @param message The message to sign. |
+ * @return signature as a byte buffer. |
+ */ |
+ @CalledByNative |
+ public static byte[] signWithPrivateKey(PrivateKey privateKey, |
+ byte[] message) { |
+ synchronized (TAG) { |
+ // Get the Signature singleton for this key. |
+ Signature signature = null; |
+ if (privateKey instanceof RSAPrivateKey) { |
+ signature = sRsaSignature; |
+ } else if (privateKey instanceof DSAPrivateKey) { |
+ signature = sDsaSignature; |
+ } else if (privateKey instanceof ECPrivateKey) { |
+ signature = sEcdsaSignature; |
+ } |
+ if (signature == null) { |
+ Log.e(TAG, "Unsupported private key algorithm: " + privateKey.getAlgorithm()); |
+ return null; |
+ } |
+ |
+ // Sign the message. |
+ try { |
+ signature.initSign(privateKey); |
+ signature.update(message); |
+ return signature.sign(); |
+ } catch (Exception e) { |
+ Log.e(TAG, "Exception while signing message with " + privateKey.getAlgorithm() + |
+ " private key: " + e); |
+ return null; |
+ } |
+ } |
+ } |
+ |
+ /** |
+ * Called from native code to return the type of a given PrivateKey |
+ * object. This is an integer that maps to one of the values defined |
+ * by org.chromium.net.SSLClientCertType, which is itself |
+ * auto-generated from net/base/ssl_client_cert_type_list.h |
+ * @param privateKey The PrivateKey handle |
+ * @return key type, or SSLClientCertType.INVALID_TYPE if unknown. |
+ */ |
+ @CalledByNative |
+ public static int getPrivateKeySigningType(PrivateKey privateKey) { |
+ if (privateKey instanceof RSAPrivateKey) |
+ return SSLClientCertType.RSA_SIGN; |
+ if (privateKey instanceof DSAPrivateKey) |
+ return SSLClientCertType.DSS_SIGN; |
+ if (privateKey instanceof ECPrivateKey) |
+ return SSLClientCertType.ECDSA_SIGN; |
+ else |
+ return SSLClientCertType.INVALID_TYPE; |
+ } |
+ |
+ // Single signature instances. Used to perform signing with private |
+ // keys. To avoid increasing Chromium's startup time, these are |
+ // created lazily by calling initSignatureForKey below. |
+ private static Signature sRsaSignature; |
+ private static Signature sDsaSignature; |
+ private static Signature sEcdsaSignature; |
+ |
+ /** |
+ * Called to ensure that the global Signature object corresponding |
+ * to a given private key is initialized before a call to signWithPrivateKey. |
+ * Note that this is a potentially blocking operation. |
+ * @param key A PrivateKey handle. |
+ */ |
+ public static void initSignatureForKey(PrivateKey key) { |
+ String algorithm = key.getAlgorithm(); |
+ synchronized (TAG) { |
+ try { |
+ // Hint: Algorithm names come from: |
+ // http://docs.oracle.com/javase/6/docs/technotes/guides/security/StandardNames.html |
+ if (algorithm.equals("RSA") && sRsaSignature == null) { |
+ // IMPORTANT: Due to what looks like a platform bug, this will |
+ // throw NoSuchAlgorithmException on Android 4.2.1. Fixed in 4.2 |
digit1
2013/01/25 14:23:41
This should read Android 4.1.2 :/
|
+ // and higher. See https://android-review.googlesource.com/#/c/40352/ |
+ sRsaSignature = Signature.getInstance("NONEwithRSA"); |
+ } else if (algorithm.equals("DSA") && sDsaSignature == null) { |
+ sDsaSignature = Signature.getInstance("NONEwithDSA"); |
+ } else if (algorithm.equals("ECDSA") && sEcdsaSignature == null) { |
+ // The documentation mentions that NONEwithECDSA is ambiguous |
+ // and that SHA1withECDSA, its synonym, should be used instead. |
+ sEcdsaSignature = Signature.getInstance("SHA1withECDSA"); |
+ } |
+ } catch (Exception e) { |
+ Log.w(TAG, "Could not create " + algorithm + " Signature singleton:" + e); |
+ } |
+ } |
+ } |
+ |
+} |