Android指紋解鎖

public class FingerprintActivity extends Activity implements OnClickListener {java

    private FingerprintManager manager;
    private CancellationSignal signal;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_fingerprint);
        findViewById(R.id.Fingerprint).setOnClickListener(this);
        manager = (FingerprintManager) getSystemService(Context.FINGERPRINT_SERVICE);
    }android

    @SuppressLint("NewApi")
    @Override
    public void onClick(View arg0) {
        switch (arg0.getId()) {
        case R.id.Fingerprint:git

            if (!manager.isHardwareDetected()) {
                Toast.makeText(this, "設備不支持", Toast.LENGTH_LONG).show();
                return;
            }
            KeyguardManager keyguardManager = (KeyguardManager) getSystemService(Context.KEYGUARD_SERVICE);
            if (!keyguardManager.isKeyguardSecure()) {
                Toast.makeText(this, "請設置圖案鎖", Toast.LENGTH_LONG).show();
                return;
            }
            if (!manager.hasEnrolledFingerprints()) {
                Toast.makeText(this, "請設置指紋", Toast.LENGTH_LONG).show();
                return;
            }安全

            try {
                CryptoObjectHelper helper = new CryptoObjectHelper();
                signal = new CancellationSignal();
                /**
                 *FingerprintManager.authenticate(CryptoObject crypto, 
                 * CancellationSignal cancel, 
                 * int flags, AuthenticationCallback callback,
                 *  Handler handler)參數解釋
                 *  1. crypto這是一個加密類的對象,指紋掃描器會使用這個對象來判斷認證結果的合法性。
                 *  這個對象能夠是null,可是這樣的話,就意味這app無條件信任認證的結果,
                 *  雖然從理論上這個過程可能被攻擊,數據能夠被篡改,
                 *  這是app在這種狀況下必須承擔的風險。所以,建議這個參數不要置爲null。
                 *  這個類的實例化有點麻煩,主要使用javax的security接口實現
                 * CryptoObjectHelper爲寫好的工具類直接引用便可
                 * 2.cancel 這個是CancellationSignal類的一個對象,
                 * 這個對象用來在指紋識別器掃描用戶指紋的是時候取消當前的掃描操做,
                 * 若是不取消的話,那麼指紋掃描器會移植掃描直到超時(通常爲30s,取決於具體的廠商實現),
                 * 這樣的話就會比較耗電。建議這個參數不要置爲null。 
                 * 3.flags 標識位,根據上圖的文檔描述,這個位暫時應該爲0,這個標誌位應該是保留未來使用的。
                 * 4.callback 這個是FingerprintManager.AuthenticationCallback類的對象,
                 * 這個是這個接口中除了第一個參數以外最重要的參數了。
                 * 當系統完成了指紋認證過程(失敗或者成功都會)後,
                 * 會回調這個對象中的接口,通知app認證的結果。這個參數不能爲NULL
                 * 5.handler 這是Handler類的對象,若是這個參數不爲null的話,
                 * 那麼FingerprintManager將會使用這個handler中的looper來處理來自指紋識別硬件的消息。
                 * 一般來說,開發這不用提供這個參數,能夠直接置爲null,
                 * 由於FingerprintManager會默認使用app的main looper來處理。
                 * 
                 * */
                manager.authenticate(helper.buildCryptoObject(), signal, 0,new MyAuthCallback(FingerprintActivity.this), null);app

            } catch (Exception e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
            break;ide

        default:
            break;
        }工具

    }
    @SuppressLint("NewApi")
    @Override
    protected void onStop() {
        // TODO Auto-generated method stub
        super.onStop();
        signal.cancel();
    }oop


}
 ui

MyAuthCallback 類this

 

public class MyAuthCallback extends AuthenticationCallback{

    private Context context;
    public MyAuthCallback(Context context){
        this.context = context;
    }

    /**
     * 這個接口會在認證成功以後回調。咱們能夠在這個方法中提示用戶認證成功。
     * 這裏須要說明一下,若是咱們上面在調用authenticate的時候,咱們的CryptoObject不是null的話,
     * 那麼咱們在這個方法中能夠經過AuthenticationResult來得到Cypher對象而後調用它的doFinal方法。
     * doFinal方法會檢查結果是否是會攔截或者篡改過,若是是的話會拋出一個異常。
     * 當咱們發現這些異常的時候都應該將認證當作是失敗來來處理,爲了安全建議你們都這麼作。 
     * 
     * */
    @Override
    public void onAuthenticationSucceeded(AuthenticationResult result) {
        // TODO Auto-generated method stub
        super.onAuthenticationSucceeded(result);
        Toast.makeText(context, "成功", Toast.LENGTH_LONG).show();
        //AuthenticationResult來得到Cypher對象而後調用它的doFinal方法。
        //doFinal方法會檢查結果是否是會攔截或者篡改過,若是是的話會拋出一個異常。
        //當咱們發現這些異常的時候都應該將認證當作是失敗來來處理,爲了安全建議你們都這麼作。 
        try {
            byte [] by =result.getCryptoObject().getCipher().doFinal();
            String date  = new String(by, "UTF-8");

            Log.e("TAG", date);

        }  catch (Exception e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }
    /**
     * 
     * 這個接口會在系統指紋認證失敗的狀況的下才會回調。注意這裏的認證失敗和上面的認證錯誤是不同的,
     * 雖然結果都是不能認證。認證失敗是指全部的信息都採集完整,而且沒有任何異常,
     * 可是這個指紋和以前註冊的指紋是不相符的;可是認證錯誤是指在採集或者認證的過程當中出現了錯誤,
     * 好比指紋傳感器工做異常等。也就是說認證失敗是一個能夠預期的正常狀況,而認證錯誤是不可預期的異常狀況。 
     * 
     * */
    @Override
    public void onAuthenticationFailed() {
        // TODO Auto-generated method stub
        super.onAuthenticationFailed();
        Toast.makeText(context, "認證失敗", Toast.LENGTH_LONG).show();
    }
    /**
     * 上面的認證失敗是認證過程當中的一個異常狀況,咱們說那種狀況是由於出現了不可恢復的錯誤,
     * 而咱們這裏的OnAuthenticationHelp方法是出現了能夠回覆的異常纔會調用的。
     * 什麼是能夠恢復的異常呢?一個常見的例子就是:
     * 手指移動太快,當咱們把手指放到傳感器上的時候,若是咱們很快地將手指移走的話,
     * 那麼指紋傳感器可能只採集了部分的信息,所以認證會失敗。
     * 可是這個錯誤是能夠恢復的,所以只要提示用戶再次按下指紋,而且不要太快移走就能夠解決。
     * 
     * */
    @Override
    public void onAuthenticationHelp(int helpCode, CharSequence helpString) {
        // TODO Auto-generated method stub
        super.onAuthenticationHelp(helpCode, helpString);
        Toast.makeText(context, "再次按下指紋", Toast.LENGTH_LONG).show();
    }
    /**
     * 這個接口會再系統指紋認證出現不可恢復的錯誤的時候纔會調用,而且參數errorCode就給出了錯誤碼,
     * 標識了錯誤的緣由。這個時候app能作的只能是提示用戶從新嘗試一遍。 
     * 
     * **/
    @Override
    public void onAuthenticationError(int errorCode, CharSequence errString) {
        // TODO Auto-generated method stub
        super.onAuthenticationError(errorCode, errString);
        Toast.makeText(context, "認證異常", Toast.LENGTH_LONG).show();
    }

}
 

 

 

/**
 * 參考連接:http://blog.csdn.net/baniel01/article/details/51991764
 * 
 * **/

 

public class CryptoObjectHelper {
    // This can be key name you want. Should be unique for the app.
    static final String KEY_NAME = "com.createchance.android.sample.fingerprint_authentication_key";

    // We always use this keystore on Android.
    static final String KEYSTORE_NAME = "AndroidKeyStore";

    // Should be no need to change these values.
    static final String KEY_ALGORITHM = KeyProperties.KEY_ALGORITHM_AES;
    static final String BLOCK_MODE = KeyProperties.BLOCK_MODE_CBC;
    static final String ENCRYPTION_PADDING = KeyProperties.ENCRYPTION_PADDING_PKCS7;
    static final String TRANSFORMATION = KEY_ALGORITHM + "/" +
            BLOCK_MODE + "/" +
            ENCRYPTION_PADDING;
    final KeyStore _keystore;

    public CryptoObjectHelper() throws Exception
    {
        _keystore = KeyStore.getInstance(KEYSTORE_NAME);
        _keystore.load(null);
    }

    //FingerprintManagerCompat.CryptoObject buildCryptoObject() 
    public FingerprintManager.CryptoObject buildCryptoObject() throws Exception{
        Cipher cipher = createCipher(true);
        return new FingerprintManager.CryptoObject(cipher);
    }

    Cipher createCipher(boolean retry) throws Exception{
        Key key = GetKey();
        Cipher cipher = Cipher.getInstance(TRANSFORMATION);
        try
        {
            cipher.init(Cipher.ENCRYPT_MODE | Cipher.DECRYPT_MODE, key);
        } catch(KeyPermanentlyInvalidatedException e)
        {
            _keystore.deleteEntry(KEY_NAME);
            if(retry)
            {
                createCipher(false);
            } else
            {
                throw new Exception("Could not create the cipher for fingerprint authentication.", e);
            }
        }
        return cipher;
    }

    Key GetKey() throws Exception
    {
        Key secretKey;
        if(!_keystore.isKeyEntry(KEY_NAME))
        {
            CreateKey();
        }

        secretKey = _keystore.getKey(KEY_NAME, null);
        return secretKey;
    }

    void CreateKey() throws Exception
    {
        KeyGenerator keyGen = KeyGenerator.getInstance(KEY_ALGORITHM, KEYSTORE_NAME);
        KeyGenParameterSpec keyGenSpec =
                new KeyGenParameterSpec.Builder(KEY_NAME, KeyProperties.PURPOSE_ENCRYPT | KeyProperties.PURPOSE_DECRYPT)
        .setBlockModes(BLOCK_MODE)
        .setEncryptionPaddings(ENCRYPTION_PADDING)
        .setUserAuthenticationRequired(true)
        .build();
        keyGen.init(keyGenSpec);
        keyGen.generateKey();
    }
}

 

 

地址:https://git.oschina.net/qswwers/Android-Fingerprint.git

相關文章
相關標籤/搜索