- Getting the response from the Yubikey through NFC
- Added TOTP class to calculate 6 digits code using RFC6238
This commit is contained in:
parent
c4f0e9ef41
commit
77b5d956ea
4 changed files with 76 additions and 39 deletions
|
@ -94,8 +94,8 @@ public class IntroActivity extends AppCompatActivity {
|
||||||
//startActivity(intent);
|
//startActivity(intent);
|
||||||
} else {
|
} else {
|
||||||
//Intent intent = new Intent(this, CreateSeedActivity.class);
|
//Intent intent = new Intent(this, CreateSeedActivity.class);
|
||||||
//Intent intent = new Intent(this, BoardActivity.class);
|
Intent intent = new Intent(this, BoardActivity.class);
|
||||||
Intent intent = new Intent(this, PocketRequestActivity.class);
|
//Intent intent = new Intent(this, PocketRequestActivity.class);
|
||||||
startActivity(intent);
|
startActivity(intent);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -64,26 +64,6 @@ public class PocketRequestActivity extends AppCompatActivity {
|
||||||
mNfcAdapter = NfcAdapter.getDefaultAdapter(this);
|
mNfcAdapter = NfcAdapter.getDefaultAdapter(this);
|
||||||
|
|
||||||
this.configureForegroundDispatch();
|
this.configureForegroundDispatch();
|
||||||
|
|
||||||
|
|
||||||
String clave = "12345678901234567890";
|
|
||||||
|
|
||||||
char[] ch = clave.toCharArray();
|
|
||||||
|
|
||||||
StringBuilder builder = new StringBuilder();
|
|
||||||
for (char c : ch) {
|
|
||||||
String hexCode=String.format("%H", c);
|
|
||||||
builder.append(hexCode);
|
|
||||||
}
|
|
||||||
String claveHex = String.format("%040x", new BigInteger(1, clave.getBytes()));
|
|
||||||
|
|
||||||
|
|
||||||
long time = 1111111109/30;
|
|
||||||
String steps = Long.toHexString(time).toUpperCase();
|
|
||||||
while(steps.length() < 16) steps = "0" + steps;
|
|
||||||
Log.i("TEST", TOTP.generateTOTP(
|
|
||||||
claveHex,
|
|
||||||
steps, "6", "HmacSHA1"));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void configureForegroundDispatch(){
|
public void configureForegroundDispatch(){
|
||||||
|
@ -130,17 +110,27 @@ public class PocketRequestActivity extends AppCompatActivity {
|
||||||
tagIsoDep.connect();
|
tagIsoDep.connect();
|
||||||
YkOathApi ykOathApi = new YkOathApi(tagIsoDep);
|
YkOathApi ykOathApi = new YkOathApi(tagIsoDep);
|
||||||
|
|
||||||
/*long unixTime = System.currentTimeMillis() / 1000L;
|
long unixTime = System.currentTimeMillis() / 1000L;
|
||||||
byte[] timeStep = ByteBuffer.allocate(8).putLong(unixTime / 30L).array();
|
byte[] timeStep = ByteBuffer.allocate(8).putLong(unixTime / 30L).array();
|
||||||
byte[] response;
|
byte[] response;
|
||||||
response = ykOathApi.calculate("cy.agorise.crystalwallet",timeStep,true);
|
response = ykOathApi.calculate("cy.agorise.crystalwallet",timeStep,true);
|
||||||
response[0].
|
ByteBuffer responseBB = ByteBuffer.wrap(response);
|
||||||
private fun formatTruncated(data: ByteArray): String {
|
int digits = (int)responseBB.get();
|
||||||
return with(ByteBuffer.wrap(data)) {
|
String challengeString = ""+(responseBB.getInt());
|
||||||
val digits = get().toInt()
|
String challenge = challengeString.substring(challengeString.length()-digits);
|
||||||
int.toString().takeLast(digits).padStart(digits, '0')
|
while (challenge.length() < digits){
|
||||||
|
challenge = '0'+challenge;
|
||||||
}
|
}
|
||||||
}*/
|
|
||||||
|
String storedChallenge = PasswordManager.totpd(yubikeySecret, unixTime, ykOathApi.getDeviceSalt());
|
||||||
|
|
||||||
|
Toast.makeText(this, "Secret:"+yubikeySecret+" StoredChallenge:"+storedChallenge+" Yubikey:"+challenge , Toast.LENGTH_LONG).show();
|
||||||
|
|
||||||
|
Log.i("TOTP","Secret: "+yubikeySecret);
|
||||||
|
Log.i("TOTP", "Unixtime: "+unixTime);
|
||||||
|
Log.i("TOTP", "Step: "+unixTime/30L);
|
||||||
|
Log.i("TOTP", "StoredChallenge: "+storedChallenge);
|
||||||
|
Log.i("TOTP", "Yubikey: "+challenge);
|
||||||
|
|
||||||
tagIsoDep.close();
|
tagIsoDep.close();
|
||||||
//ykOathApi.
|
//ykOathApi.
|
||||||
|
|
|
@ -1,5 +1,11 @@
|
||||||
package cy.agorise.crystalwallet.util;
|
package cy.agorise.crystalwallet.util;
|
||||||
|
|
||||||
|
import android.util.Log;
|
||||||
|
|
||||||
|
import java.math.BigInteger;
|
||||||
|
|
||||||
|
import cy.agorise.crystalwallet.util.yubikey.TOTP;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Created by Henry Varona on 29/1/2018.
|
* Created by Henry Varona on 29/1/2018.
|
||||||
*/
|
*/
|
||||||
|
@ -19,4 +25,35 @@ public class PasswordManager {
|
||||||
public static String encriptPassword(String password){
|
public static String encriptPassword(String password){
|
||||||
return password;
|
return password;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static String totpd(String sharedSecret, long unixtime, byte[] salt){
|
||||||
|
char[] ch = sharedSecret.toCharArray();
|
||||||
|
|
||||||
|
StringBuilder builder = new StringBuilder();
|
||||||
|
for (char c : ch) {
|
||||||
|
String hexCode=String.format("%H", c);
|
||||||
|
builder.append(hexCode);
|
||||||
|
}
|
||||||
|
String secretHex = String.format("%040x", new BigInteger(1, sharedSecret.getBytes()));
|
||||||
|
|
||||||
|
long time = unixtime/30L;
|
||||||
|
|
||||||
|
String steps = Long.toHexString(time).toUpperCase();
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*for (int i=0;i<64;i++){
|
||||||
|
steps = Long.toHexString(time+i).toUpperCase();
|
||||||
|
Log.i("TOTPTEST", TOTP.generateTOTP(
|
||||||
|
secretHex,
|
||||||
|
steps,
|
||||||
|
"6", "HmacSHA1", salt));
|
||||||
|
secretHex = "00"+secretHex;
|
||||||
|
}*/
|
||||||
|
|
||||||
|
return TOTP.generateTOTP(
|
||||||
|
secretHex,
|
||||||
|
steps,
|
||||||
|
"6", "HmacSHA1", salt);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,6 +6,8 @@ import java.text.DateFormat;
|
||||||
import java.text.SimpleDateFormat;
|
import java.text.SimpleDateFormat;
|
||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
import javax.crypto.Mac;
|
import javax.crypto.Mac;
|
||||||
|
import javax.crypto.SecretKeyFactory;
|
||||||
|
import javax.crypto.spec.PBEKeySpec;
|
||||||
import javax.crypto.spec.SecretKeySpec;
|
import javax.crypto.spec.SecretKeySpec;
|
||||||
import java.math.BigInteger;
|
import java.math.BigInteger;
|
||||||
import java.util.TimeZone;
|
import java.util.TimeZone;
|
||||||
|
@ -30,7 +32,7 @@ public class TOTP {
|
||||||
*/
|
*/
|
||||||
|
|
||||||
private static byte[] hmac_sha(String crypto, byte[] keyBytes,
|
private static byte[] hmac_sha(String crypto, byte[] keyBytes,
|
||||||
byte[] text){
|
byte[] text, byte[] salt){
|
||||||
try {
|
try {
|
||||||
Mac hmac;
|
Mac hmac;
|
||||||
hmac = Mac.getInstance(crypto);
|
hmac = Mac.getInstance(crypto);
|
||||||
|
@ -38,6 +40,10 @@ public class TOTP {
|
||||||
new SecretKeySpec(keyBytes, "RAW");
|
new SecretKeySpec(keyBytes, "RAW");
|
||||||
hmac.init(macKey);
|
hmac.init(macKey);
|
||||||
return hmac.doFinal(text);
|
return hmac.doFinal(text);
|
||||||
|
/*PBEKeySpec spec = new PBEKeySpec((new String(text)).toCharArray(), salt, 1000, 128);
|
||||||
|
SecretKeyFactory skf = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA1");
|
||||||
|
byte[] hash = skf.generateSecret(spec).getEncoded();
|
||||||
|
return hash;*/
|
||||||
} catch (GeneralSecurityException gse) {
|
} catch (GeneralSecurityException gse) {
|
||||||
throw new UndeclaredThrowableException(gse);
|
throw new UndeclaredThrowableException(gse);
|
||||||
}
|
}
|
||||||
|
@ -82,8 +88,9 @@ public class TOTP {
|
||||||
|
|
||||||
public static String generateTOTP(String key,
|
public static String generateTOTP(String key,
|
||||||
String time,
|
String time,
|
||||||
String returnDigits){
|
String returnDigits,
|
||||||
return generateTOTP(key, time, returnDigits, "HmacSHA1");
|
byte[] salt){
|
||||||
|
return generateTOTP(key, time, returnDigits, "PBKDF2WithHmacSHA1", salt);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -101,8 +108,9 @@ public class TOTP {
|
||||||
|
|
||||||
public static String generateTOTP256(String key,
|
public static String generateTOTP256(String key,
|
||||||
String time,
|
String time,
|
||||||
String returnDigits){
|
String returnDigits,
|
||||||
return generateTOTP(key, time, returnDigits, "HmacSHA256");
|
byte[] salt){
|
||||||
|
return generateTOTP(key, time, returnDigits, "HmacSHA256", salt);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -119,8 +127,9 @@ public class TOTP {
|
||||||
|
|
||||||
public static String generateTOTP512(String key,
|
public static String generateTOTP512(String key,
|
||||||
String time,
|
String time,
|
||||||
String returnDigits){
|
String returnDigits,
|
||||||
return generateTOTP(key, time, returnDigits, "HmacSHA512");
|
byte[] salt){
|
||||||
|
return generateTOTP(key, time, returnDigits, "HmacSHA512", salt);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -140,7 +149,8 @@ public class TOTP {
|
||||||
public static String generateTOTP(String key,
|
public static String generateTOTP(String key,
|
||||||
String time,
|
String time,
|
||||||
String returnDigits,
|
String returnDigits,
|
||||||
String crypto){
|
String crypto,
|
||||||
|
byte[] salt){
|
||||||
int codeDigits = Integer.decode(returnDigits).intValue();
|
int codeDigits = Integer.decode(returnDigits).intValue();
|
||||||
String result = null;
|
String result = null;
|
||||||
|
|
||||||
|
@ -153,7 +163,7 @@ public class TOTP {
|
||||||
// Get the HEX in a Byte[]
|
// Get the HEX in a Byte[]
|
||||||
byte[] msg = hexStr2Bytes(time);
|
byte[] msg = hexStr2Bytes(time);
|
||||||
byte[] k = hexStr2Bytes(key);
|
byte[] k = hexStr2Bytes(key);
|
||||||
byte[] hash = hmac_sha(crypto, k, msg);
|
byte[] hash = hmac_sha(crypto, k, msg, salt);
|
||||||
|
|
||||||
// put selected bytes into result int
|
// put selected bytes into result int
|
||||||
int offset = hash[hash.length - 1] & 0xf;
|
int offset = hash[hash.length - 1] & 0xf;
|
||||||
|
|
Loading…
Reference in a new issue