[英]Capture fingerprint from smartphone and save to a file
我正在做一個項目,我需要使用NFC連接將指紋掃描捕獲的結果傳輸到本地服務器,然后從服務器接收答案。
到目前為止,我設法了解如何使用谷歌的API進行傳輸和掃描fringerprint,但問題是我無法將掃描結果發送給服務器以完成身份驗證。
我正在使用API23的谷歌指紋庫。
主要活動:
package com.gmtechnology.smartalarm;
import android.Manifest;
import android.app.KeyguardManager;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.hardware.fingerprint.FingerprintManager;
import android.net.Uri;
import android.nfc.NdefMessage;
import android.nfc.NdefRecord;
import android.nfc.NfcAdapter;
import android.os.Build;
import android.os.Bundle;
import android.os.Environment;
import android.provider.Settings;
import android.security.keystore.KeyGenParameterSpec;
import android.security.keystore.KeyPermanentlyInvalidatedException;
import android.security.keystore.KeyProperties;
import android.support.design.widget.FloatingActionButton;
import android.support.design.widget.NavigationView;
import android.support.v4.app.ActivityCompat;
import android.support.v4.view.GravityCompat;
import android.support.v4.widget.DrawerLayout;
import android.support.v7.app.ActionBarDrawerToggle;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.Toolbar;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.widget.TextView;
import android.widget.Toast;
import java.io.File;
import java.io.IOException;
import java.security.InvalidAlgorithmParameterException;
import java.security.InvalidKeyException;
import java.security.KeyStore;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.security.NoSuchProviderException;
import java.security.UnrecoverableKeyException;
import java.security.cert.CertificateException;
import javax.crypto.Cipher;
import javax.crypto.KeyGenerator;
import javax.crypto.NoSuchPaddingException;
import javax.crypto.SecretKey;
public class MainActivity extends AppCompatActivity
implements NavigationView.OnNavigationItemSelectedListener {
private static final String KEY_NAME = "main_key";
protected FingerprintManager fingerprintManager;
protected KeyguardManager keyguardManager;
private KeyStore keyStore;
protected KeyGenerator keyGenerator;
private Cipher cipher;
protected FingerprintManager.CryptoObject cryptoObject;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
TextView state = (TextView) findViewById(R.id.state);
FloatingActionButton lock = (FloatingActionButton) findViewById(R.id.lock);
FloatingActionButton unlock = (FloatingActionButton) findViewById(R.id.unlock);
FloatingActionButton start = (FloatingActionButton) findViewById(R.id.start);
FloatingActionButton stop = (FloatingActionButton) findViewById(R.id.stop);
PackageManager pm = this.getPackageManager();
// Check whether NFC is available on device
if (!pm.hasSystemFeature(PackageManager.FEATURE_NFC)) {
// NFC is not available on the device.
Toast.makeText(this, "The device does not has NFC hardware",
Toast.LENGTH_SHORT).show();
}
// Check whether device is running Android 4.1 or higher
else if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) {
// Android Beam feature is not supported.
Toast.makeText(this, "Wrong android version",
Toast.LENGTH_SHORT).show();
}
keyguardManager =
(KeyguardManager) getSystemService(KEYGUARD_SERVICE);
fingerprintManager =
(FingerprintManager) getSystemService(FINGERPRINT_SERVICE);
if (!keyguardManager.isKeyguardSecure()) {
Toast.makeText(this,
"Lock screen security not enabled in Settings",
Toast.LENGTH_LONG).show();
return;
}
if (ActivityCompat.checkSelfPermission(this,
Manifest.permission.USE_FINGERPRINT) !=
PackageManager.PERMISSION_GRANTED) {
Toast.makeText(this,
"Fingerprint authentication permission not enabled",
Toast.LENGTH_LONG).show();
return;
}
if (!fingerprintManager.hasEnrolledFingerprints()) {
// This happens when no fingerprints are registered.
Toast.makeText(this,
"Register at least one fingerprint in Settings",
Toast.LENGTH_LONG).show();
return;
}
generateKey();
if (cipherInit()) {
cryptoObject = new FingerprintManager.CryptoObject(cipher);
//cryptoObject == the scanned fingerprint
FingerprintHandler helper = new FingerprintHandler(this);
helper.startAuth(fingerprintManager, cryptoObject, lock, unlock, start, stop, state);
}
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
DrawerLayout drawer = (DrawerLayout) findViewById(R.id.drawer_layout);
ActionBarDrawerToggle toggle = new ActionBarDrawerToggle(
this, drawer, toolbar, R.string.navigation_drawer_open, R.string.navigation_drawer_close);
drawer.setDrawerListener(toggle);
toggle.syncState();
NavigationView navigationView = (NavigationView) findViewById(R.id.nav_view);
navigationView.setNavigationItemSelectedListener(this);
state(1, lock, unlock, start, stop, state);
}
public void sendFile(View view) {
NfcAdapter nfcAdapter = NfcAdapter.getDefaultAdapter(this);
String command = "command";
if(!nfcAdapter.isEnabled()){
Toast.makeText(this, "Please enable NFC.",
Toast.LENGTH_SHORT).show();
startActivity(new Intent(Settings.ACTION_NFC_SETTINGS));
}
else if(!nfcAdapter.isNdefPushEnabled()) {
Toast.makeText(this, "Please enable Android Beam.",
Toast.LENGTH_SHORT).show();
startActivity(new Intent(Settings.ACTION_NFCSHARING_SETTINGS));
}
else {
if(view.getId() == R.id.lock) {
command = "lock";
}
else if(view.getId() == R.id.unlock) {
command = "unlock";
}
else if(view.getId() == R.id.start) {
command = "start";
}
else if(view.getId() == R.id.stop) {
command = "stop";
}
NdefRecord ndefRecord = NdefRecord.createMime("text/plain", command.getBytes());
NdefMessage ndefMessage = new NdefMessage(ndefRecord);
String fileName = "wallpaper.png";
// Retrieve the path to the user's public pictures directory
File fileDirectory = Environment
.getExternalStoragePublicDirectory(
Environment.DIRECTORY_PICTURES);
// Create a new file using the specified directory and name
File fileToTransfer = new File(fileDirectory, fileName);
fileToTransfer.setReadable(true, false);
nfcAdapter.setBeamPushUris(
new Uri[]{Uri.fromFile(fileToTransfer)}, this);
nfcAdapter.setNdefPushMessage(ndefMessage, this);
}
}
protected void generateKey() {
try {
keyStore = KeyStore.getInstance("AndroidKeyStore");
} catch (Exception e) {
e.printStackTrace();
}
try {
keyGenerator = KeyGenerator.getInstance(
KeyProperties.KEY_ALGORITHM_AES,
"AndroidKeyStore");
} catch (NoSuchAlgorithmException |
NoSuchProviderException e) {
throw new RuntimeException(
"Failed to get KeyGenerator instance", e);
}
try {
keyStore.load(null);
keyGenerator.init(new
KeyGenParameterSpec.Builder(KEY_NAME,
KeyProperties.PURPOSE_ENCRYPT |
KeyProperties.PURPOSE_DECRYPT)
.setBlockModes(KeyProperties.BLOCK_MODE_CBC)
.setUserAuthenticationRequired(true)
.setEncryptionPaddings(
KeyProperties.ENCRYPTION_PADDING_PKCS7)
.build());
keyGenerator.generateKey();
} catch (NoSuchAlgorithmException |
InvalidAlgorithmParameterException
| CertificateException | IOException e) {
throw new RuntimeException(e);
}
}
public boolean cipherInit() {
try {
cipher = Cipher.getInstance(
KeyProperties.KEY_ALGORITHM_AES + "/"
+ KeyProperties.BLOCK_MODE_CBC + "/"
+ KeyProperties.ENCRYPTION_PADDING_PKCS7);
} catch (NoSuchAlgorithmException |
NoSuchPaddingException e) {
throw new RuntimeException("Failed to get Cipher", e);
}
try {
keyStore.load(null);
SecretKey key = (SecretKey) keyStore.getKey(KEY_NAME,
null);
cipher.init(Cipher.ENCRYPT_MODE, key);
return true;
} catch (KeyPermanentlyInvalidatedException e) {
return false;
} catch (KeyStoreException | CertificateException
| UnrecoverableKeyException | IOException
| NoSuchAlgorithmException | InvalidKeyException e) {
throw new RuntimeException("Failed to init Cipher", e);
}
}
@Override
public void onBackPressed() {
DrawerLayout drawer = (DrawerLayout) findViewById(R.id.drawer_layout);
if (drawer.isDrawerOpen(GravityCompat.START)) {
drawer.closeDrawer(GravityCompat.START);
} else {
super.onBackPressed();
}
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.main, menu);
return true;
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
// Handle action bar item clicks here. The action bar will
// automatically handle clicks on the Home/Up button, so long
// as you specify a parent activity in AndroidManifest.xml.
int id = item.getItemId();
//noinspection SimplifiableIfStatement
if (id == R.id.action_settings) {
return true;
}
return super.onOptionsItemSelected(item);
}
@SuppressWarnings("StatementWithEmptyBody")
@Override
public boolean onNavigationItemSelected(MenuItem item) {
// Handle navigation view item clicks here.
int id = item.getItemId();
if (id == R.id.nav_camera) {
// Handle the camera action
} else if (id == R.id.nav_gallery) {
} else if (id == R.id.nav_share) {
} else if (id == R.id.nav_send) {
}
DrawerLayout drawer = (DrawerLayout) findViewById(R.id.drawer_layout);
drawer.closeDrawer(GravityCompat.START);
return true;
}
public void state (int s, FloatingActionButton lock, FloatingActionButton unlock, FloatingActionButton start, FloatingActionButton stop, TextView state) {
if (s == 1) {
state.setText(R.string.scan);
state.setTextColor(0xFF970E0E);
lock.setEnabled(false);
lock.hide();
unlock.setEnabled(false);
unlock.hide();
start.setEnabled(false);
start.hide();
stop.setEnabled(false);
stop.hide();
}
if (s == 2) {
state.setText(R.string.done);
state.setTextColor(0xFF149926);
lock.setEnabled(true);
lock.show();
unlock.setEnabled(true);
unlock.show();
start.setEnabled(true);
start.show();
stop.setEnabled(true);
stop.show();
}
if (s == 3) {
state.setText(R.string.error);
state.setTextColor(0xFF970E0E);
lock.setEnabled(false);
lock.hide();
unlock.setEnabled(false);
unlock.hide();
start.setEnabled(false);
start.hide();
stop.setEnabled(false);
stop.hide();
}
}
}
FingerprintHandler:
package com.gmtechnology.smartalarm;
import android.Manifest;
import android.content.Context;
import android.content.pm.PackageManager;
import android.hardware.fingerprint.FingerprintManager;
import android.os.CancellationSignal;
import android.support.design.widget.FloatingActionButton;
import android.support.v4.app.ActivityCompat;
import android.widget.TextView;
public class FingerprintHandler extends
FingerprintManager.AuthenticationCallback {
protected CancellationSignal cancellationSignal;
private Context appContext;
private FloatingActionButton mlock;
private FloatingActionButton mstart;
private FloatingActionButton munlock;
private FloatingActionButton mstop;
private TextView mstate;
public FingerprintHandler(Context context) {
appContext = context;
}
public void startAuth(FingerprintManager manager,
FingerprintManager.CryptoObject cryptoObject, FloatingActionButton lock, FloatingActionButton unlock, FloatingActionButton start, FloatingActionButton stop, TextView state) {
mlock = lock;
munlock = unlock;
mstart = start;
mstop = stop;
mstate = state;
cancellationSignal = new CancellationSignal();
if (ActivityCompat.checkSelfPermission(appContext,
Manifest.permission.USE_FINGERPRINT) !=
PackageManager.PERMISSION_GRANTED) {
return;
}
manager.authenticate(cryptoObject, cancellationSignal, 0, this, null);
}
@Override
public void onAuthenticationHelp(int helpMsgId,
CharSequence helpString) {
new MainActivity().state(3, mlock, munlock, mstart, mstop, mstate);
}
@Override
public void onAuthenticationFailed() {
new MainActivity().state(3, mlock, munlock, mstart, mstop, mstate);
}
@Override
public void onAuthenticationSucceeded(
FingerprintManager.AuthenticationResult result) {
new MainActivity().state(2, mlock, munlock, mstart, mstop, mstate);
}
}
如果有人能指出我如何捕獲並將掃描結果轉換為我可以通過NFC發送它的格式,那將是非常棒的!
PS:我不是程序員,請放輕松我T ^ T
根據Micheal答案重申可能性:無論如何都要使用NFC將傳感器直接連接到服務器,以便數據可以直接發送到服務器進行身份驗證而不保存? 整個想法是認證是由外部服務器而不是智能手機完成的,這樣使智能手機成為“通用密鑰”,因此任何智能手機都可以用於向任何服務器進行身份驗證,當然使用正確的應用程序,或者以某種方式欺騙智能手機使用數據庫連接通過NFC來比較指紋,這樣當前信息在安全的內存上,但用於比較指紋的數據庫是在遠程服務器上。 我知道這些聽起來很棘手,甚至可能“瘋狂”,但是如果有可能在“適當的”方式之外做到這一點,那么它只適用於研究和研究。
Android指紋身份驗證專門設計用於無法執行您想要的操作。
該設計確保指紋圖像數據永遠不會在Android OS 中可用。 即使您根設備或破壞內核,這些數據根本不可用。 指紋圖像需要從指紋掃描儀安全地傳遞到進行指紋匹配的安全硬件。 這實際上是Android合規性要求。 原因是指紋是重要的個人信息,不應泄露。
關於你的替代建議,我無法想象為什么任何制造商都會這樣做。
如果您想使用Android作為通用密鑰,您應該執行以下操作:
Signature
對象,將其初始化並將其包裝在FingerprintManager.CryptoObject
。 如果您想在服務器上進行指紋驗證,則需要使用其他類型的指紋掃描儀。 您無法使用Android(或iOS)手機執行此操作。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.