Skip to content
This repository has been archived by the owner on Sep 13, 2024. It is now read-only.

Commit

Permalink
Merge pull request #22 from coderbunker/issue#5-hotp
Browse files Browse the repository at this point in the history
Finished HOTP implementation
  • Loading branch information
julianschmuckli committed Aug 9, 2018
2 parents 24e79b8 + 09a0992 commit b5cbf27
Show file tree
Hide file tree
Showing 7 changed files with 249 additions and 25 deletions.
Binary file modified .idea/caches/build_file_checksums.ser
Binary file not shown.
4 changes: 3 additions & 1 deletion app/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,9 @@
android:screenOrientation="landscape">

</activity>
<activity android:name=".KioskActivity">
<activity
android:name=".KioskActivity"
android:screenOrientation="landscape">
<intent-filter>
<action android:name="android.intent.action.MAIN" />

Expand Down
29 changes: 25 additions & 4 deletions app/src/main/java/com/coderbunker/kioskapp/KioskActivity.java
Original file line number Diff line number Diff line change
Expand Up @@ -15,14 +15,16 @@
import android.view.Window;
import android.view.WindowManager;
import android.webkit.SslErrorHandler;
import android.webkit.WebChromeClient;
import android.webkit.WebView;
import android.webkit.WebViewClient;
import android.widget.Button;
import android.widget.Toast;

import com.coderbunker.kioskapp.lib.HOTP;
import com.coderbunker.kioskapp.lib.TOTP;

import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
Expand Down Expand Up @@ -85,11 +87,16 @@ protected void onCreate(Bundle savedInstanceState) {
webView = findViewById(R.id.webview);
webView.setWebViewClient(new WebViewClient() {
@Override
public void onPageFinished(WebView view, String url) {
public void onPageFinished(final WebView view, String url) {
super.onPageFinished(view, url);
TimerTask lock = new TimerTask() {
@Override
public void run() {
runOnUiThread(new Runnable() {
public void run() {
Toast.makeText(context, "Kioskmode locked", Toast.LENGTH_SHORT).show();
}
});
locked = true;
}
};
Expand Down Expand Up @@ -134,7 +141,6 @@ public boolean onTouch(View view, MotionEvent motionEvent) {
});

numbers = new ArrayList<Button>();

}


Expand Down Expand Up @@ -224,6 +230,7 @@ private void launchHome() {

private void checkPwd() {
String otp = prefs.getString("otp", null);
int hotp_counter = prefs.getInt("hotp_counter", 0);
if (otp == null) {
Toast.makeText(context, "Please go to the settings and create a password", Toast.LENGTH_SHORT).show();
launchHome();
Expand All @@ -232,8 +239,22 @@ private void checkPwd() {
String generated_number = TOTP.generateCurrentNumber(otp, System.currentTimeMillis());
String previous_generated_number = TOTP.generateCurrentNumber(otp, System.currentTimeMillis() - 30000);


//HOTP
for (int i = 0; i < 10; i++) {
if (pwd.equals(HOTP.generateHOTP(hotp_counter - 5 + i, otp))) {
Toast.makeText(context, "HOTP PIN correct", Toast.LENGTH_SHORT).show();

hotp_counter++;
prefs.edit().putInt("hotp_counter", hotp_counter).apply();

launchHome();
}
}

//TOTP
if (pwd.equals(generated_number) || pwd.equals(previous_generated_number)) {
Toast.makeText(context, "PIN correct", Toast.LENGTH_SHORT).show();
Toast.makeText(context, "TOTP PIN correct", Toast.LENGTH_SHORT).show();
launchHome();
} else {
dialog.dismiss();
Expand Down
55 changes: 49 additions & 6 deletions app/src/main/java/com/coderbunker/kioskapp/SettingsActivity.java
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,14 @@

import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.graphics.Bitmap;
import android.graphics.Color;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.KeyEvent;
import android.view.MenuItem;
import android.view.View;
import android.webkit.URLUtil;
import android.widget.Button;
Expand All @@ -28,25 +30,29 @@ public class SettingsActivity extends Activity {

private Context context = this;
private EditText editURL;
private ImageView imgQRCode;
private ImageView imgQRCode, imgQRCodeHOTP;
private TextView lblCurrentHOTPCycle;
private Button btnSave;

private SharedPreferences prefs;

private String otp_uri;
private String otp_uri, hotp_uri;

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_settings);

getActionBar().setDisplayHomeAsUpEnabled(true);

prefs = this.getSharedPreferences(
"com.coderbunker.kioskapp", Context.MODE_PRIVATE);

imgQRCode = findViewById(R.id.imgQRCode);
imgQRCodeHOTP = findViewById(R.id.imgQRCodeHOTP);
editURL = findViewById(R.id.editText_URL);
btnSave = findViewById(R.id.btnSave);

lblCurrentHOTPCycle = findViewById(R.id.current_hotp_cycle);

btnSave.setOnClickListener(new View.OnClickListener() {
@Override
Expand All @@ -66,9 +72,12 @@ public void onClick(View v) {

String otp = prefs.getString("otp", null);
String url = prefs.getString("url", "https://naibaben.github.io/");
int hotp_counter = prefs.getInt("hotp_counter", 0);

editURL.setText(url);

lblCurrentHOTPCycle.setText("Current counter cycle: " + hotp_counter);

if (otp == null) {

byte key_1 = (byte) Math.floor(Math.random() * 10);
Expand All @@ -88,12 +97,14 @@ public void onClick(View v) {
editor.apply();
}

otp_uri = "otpauth://totp/Admin?secret=" + otp + "&issuer=Coderbunker";
otp_uri = "otpauth://totp/Time%20based?secret=" + otp + "&issuer=Kiosk%20Coderbunker";
hotp_uri = "otpauth://hotp/Hash%20based?secret=" + otp + "&issuer=Kiosk%20Coderbunker&counter=" + (hotp_counter - 1) + "&algorithm=SHA1";

generateQRCode(otp_uri);
generateQRCodeTOTP(otp_uri);
generateQRCodeHOTP(hotp_uri);
}

private void generateQRCode(String uri) {
private void generateQRCodeTOTP(String uri) {
QRCodeWriter writer = new QRCodeWriter();
try {
BitMatrix bitMatrix = writer.encode(uri, BarcodeFormat.QR_CODE, 512, 512);
Expand All @@ -111,4 +122,36 @@ private void generateQRCode(String uri) {
e.printStackTrace();
}
}

private void generateQRCodeHOTP(String uri) {
QRCodeWriter writer = new QRCodeWriter();
try {
BitMatrix bitMatrix = writer.encode(uri, BarcodeFormat.QR_CODE, 512, 512);
int width = bitMatrix.getWidth();
int height = bitMatrix.getHeight();
Bitmap bmp = Bitmap.createBitmap(width, height, Bitmap.Config.RGB_565);
for (int x = 0; x < width; x++) {
for (int y = 0; y < height; y++) {
bmp.setPixel(x, y, bitMatrix.get(x, y) ? Color.BLACK : Color.WHITE);
}
}
imgQRCodeHOTP.setImageBitmap(bmp);

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

@Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case android.R.id.home:
Intent intent = new Intent(SettingsActivity.this, MainActivity.class);
startActivity(intent);
finish();
return true;
default:
return super.onOptionsItemSelected(item);
}
}
}
100 changes: 100 additions & 0 deletions app/src/main/java/com/coderbunker/kioskapp/lib/HOTP.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
/*
* HOTP.java
* OATH Initiative,
* HOTP one-time password algorithm
*
*/

/* Copyright (C) 2004, OATH. All rights reserved.
*
* License to copy and use this software is granted provided that it
* is identified as the "OATH HOTP Algorithm" in all material
* mentioning or referencing this software or this function.
*
* License is also granted to make and use derivative works provided
* that such works are identified as
* "derived from OATH HOTP algorithm"
* in all material mentioning or referencing the derived work.
*
* OATH (Open AuTHentication) and its members make no
* representations concerning either the merchantability of this
* software or the suitability of this software for any particular
* purpose.
*
* It is provided "as is" without express or implied warranty
* of any kind and OATH AND ITS MEMBERS EXPRESSaLY DISCLAIMS
* ANY WARRANTY OR LIABILITY OF ANY KIND relating to this software.
*
* These notices must be retained in any copies of any part of this
* documentation and/or software.
*/

package com.coderbunker.kioskapp.lib;

import java.lang.reflect.UndeclaredThrowableException;
import java.security.GeneralSecurityException;

import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;

/**
* This class contains static methods that are used to calculate the
* One-Time Password (OTP) using
* JCE to provide the HMAC-SHA-1.
*
* @author Loren Hart
* @version 1.0
*/
public class HOTP {
public static final int[] DIGITS_POWER
// 0 1 2 3 4 5 6 7 8
= {1, 10, 100, 1000, 10000, 100000, 1000000, 10000000, 100000000};

public static String generateHOTP(long count, String seedString) {

byte[] counter = new byte[8];
long movingFactor = count;

for (int i = counter.length - 1; i >= 0; i--) {
counter[i] = (byte) (movingFactor & 0xff);
movingFactor >>= 8;
}
byte[] seed = new byte[0];
try {
seed = Base32.decode(seedString);
} catch (Base32.DecodingException e) {
e.printStackTrace();
}


byte[] hash = HMAC(seed, counter);
int offset = hash[hash.length - 1] & 0xf;

int otpBinary = ((hash[offset] & 0x7f) << 24)
| ((hash[offset + 1] & 0xff) << 16)
| ((hash[offset + 2] & 0xff) << 8)
| (hash[offset + 3] & 0xff);

int otp = otpBinary % DIGITS_POWER[6];
String result = Integer.toString(otp);

while (result.length() < 6) {
result = "0" + result;
}
return result;

}

private static byte[] HMAC(byte[] seed, byte[] counter) {

try {
Mac hmac = Mac.getInstance("HmacSHA1");
SecretKeySpec macKey = new SecretKeySpec(seed, "RAW");
hmac.init(macKey);
return hmac.doFinal(counter);

} catch (GeneralSecurityException ex) {
throw new UndeclaredThrowableException(ex);
}
}
}
84 changes: 71 additions & 13 deletions app/src/main/res/layout/activity_settings.xml
Original file line number Diff line number Diff line change
Expand Up @@ -19,21 +19,79 @@
android:orientation="vertical">


<TextView
android:id="@+id/textView_otp"
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center_horizontal"
android:paddingVertical="20dp"
android:text="TOTP"
android:textColor="@android:color/black"
android:textSize="22dp" />
android:layout_height="match_parent"
android:orientation="horizontal">

<ImageView
android:id="@+id/imgQRCode"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:src="@drawable/ic_launcher_background" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_weight="1"
android:orientation="vertical">

<TextView
android:id="@+id/textView_otp"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_weight="1"
android:gravity="center_horizontal"
android:paddingVertical="20dp"
android:text="Time based"
android:textColor="@android:color/black"
android:textSize="22dp" />

<ImageView
android:id="@+id/imgQRCode"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_weight="1"
android:src="@drawable/ic_launcher_background" />

<TextView
android:id="@+id/placeholder"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_weight="1"
android:textAlignment="center" />

</LinearLayout>

<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_weight="1"
android:orientation="vertical">

<TextView
android:id="@+id/textView_hotp"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_weight="1"
android:gravity="center_horizontal"
android:paddingVertical="20dp"
android:text="Counter based"
android:textColor="@android:color/black"
android:textSize="22dp" />

<ImageView
android:id="@+id/imgQRCodeHOTP"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_weight="1"
android:src="@drawable/ic_launcher_background" />

<TextView
android:id="@+id/current_hotp_cycle"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="Current cycle: ---"
android:textAlignment="center" />

</LinearLayout>

</LinearLayout>

<TextView
android:id="@+id/textView_URL"
Expand Down
Loading

0 comments on commit b5cbf27

Please sign in to comment.