Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

java python golang #7

Open
wants to merge 5 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 1 addition & 13 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,13 +1 @@
Simple CLI app that generates tokens compatible with Google Authenticator. I implemented this mainly to understand how it works, you should probably not use this.

Example output:

```sh
$ go run main.go "<your key>"
934523 (17 second(s) remaining)
```

Relevant RFCs:

* http://tools.ietf.org/html/rfc4226
* http://tools.ietf.org/html/rfc6238
Simple CLI apps that generate tokens compatible with Google Authenticator.
File renamed without changes.
13 changes: 13 additions & 0 deletions golang/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
Simple CLI app that generates tokens compatible with Google Authenticator. I implemented this mainly to understand how it works, you should probably not use this.

Example output:

```sh
$ go run main.go "<your key>"
934523 (17 second(s) remaining)
```

Relevant RFCs:

* http://tools.ietf.org/html/rfc4226
* http://tools.ietf.org/html/rfc6238
File renamed without changes.
9 changes: 9 additions & 0 deletions java/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
.gradle/
gradlew
gradlew.bat
bin/
build/
gradle/
.project
.classpath
.settings/
9 changes: 9 additions & 0 deletions java/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@

# Java TOTP

```bash
foo@bar:~$ gradle wrapper
foo@bar:~$ ./gradlew clean
foo@bar:~$ ./gradlew build
foo@bar:~$ ./gradlew --console plain run
```
32 changes: 32 additions & 0 deletions java/build.gradle
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
apply plugin:'application'
mainClassName = "common.TwoFactorAuth"

buildscript {
repositories {
mavenCentral()
//jcenter()
jcenter {
url "http://jcenter.bintray.com/"
}
}
}

repositories {
//jcenter()
jcenter {
url "http://jcenter.bintray.com/"
}
}

apply plugin: 'java'

dependencies {
compile group: 'com.google.guava', name: 'guava', version: '25.1-jre'
compile group: 'commons-codec', name: 'commons-codec', version: '1.12'

}

run{
standardInput = System.in
}

80 changes: 80 additions & 0 deletions java/src/main/java/common/TwoFactorAuth.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
package common;

import com.google.common.primitives.UnsignedBytes;
import org.apache.commons.codec.binary.Base32;

import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.util.Arrays;
import java.util.Scanner;

/**
* <b>Pseudocode for one-time password (OTP)</b>
* <pre>
* function GoogleAuthenticatorCode(string secret)
* key := 5B5E7MMX344QRHYO
* message := floor(current Unix time / 30)
* hash := HMAC-SHA1(key, message)
* offset := last nibble of hash
* truncatedHash := hash[offset..offset+3] //4 bytes starting at the offset
* Set the first bit of truncatedHash to zero //remove the most significant bit
* code := truncatedHash mod 1000000
* pad code with 0 from the left until length of code is 6
* return code
* </pre>
*
* @see <a href="https://en.wikipedia.org/wiki/Google_Authenticator">Wiki</a>
*/
public class TwoFactorAuth {
private static final String HMAC_SHA1 = "HmacSHA1";
private static final short[] SHIFTS = {56, 48, 40, 32, 24, 16, 8, 0};

private static byte[] toBytes(long value) {
byte[] result = new byte[8];
for (int i = 0; i < SHIFTS.length; i++) {
result[i] = (byte) ((value >> SHIFTS[i]) & 0xFF);
}
return result;
}

private static int toUint32(byte[] bytes) {
return (UnsignedBytes.toInt(bytes[0]) << 24)
+ (UnsignedBytes.toInt(bytes[1]) << 16)
+ (UnsignedBytes.toInt(bytes[2]) << 8)
+ (UnsignedBytes.toInt(bytes[3]));
}

private static int oneTimePassword(byte[] key, byte[] value) throws InvalidKeyException, NoSuchAlgorithmException {
Mac mac = Mac.getInstance(HMAC_SHA1);
mac.init(new SecretKeySpec(key, HMAC_SHA1));
mac.update(value);
byte[] hash = mac.doFinal();

int offset = hash[hash.length - 1] & 0x0F;

byte[] truncatedHash = Arrays.copyOfRange(hash, offset, offset + 4);

truncatedHash[0] = (byte) (truncatedHash[0] & 0x7F);

long number = toUint32(truncatedHash);

return (int) (number % 1000000);
}

public static void main(String[] args) throws NoSuchAlgorithmException, InvalidKeyException {
Scanner scanner = new Scanner(System.in);
System.out.print("Input key:");
String input = scanner.nextLine();
scanner.close();

byte[] key = new Base32().decode(input);
long epochSeconds = System.currentTimeMillis() / 1000;
int pwd = oneTimePassword(key, toBytes(epochSeconds / 30));
long secondsRemaining = 30 - (epochSeconds % 30);

System.out.println(String.format("%06d (%d second(s) remaining)", pwd, secondsRemaining));
}
}

20 changes: 20 additions & 0 deletions python3/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
# TOTP Authenticator in Python

* https://medium.freecodecamp.org/how-time-based-one-time-passwords-work-and-why-you-should-use-them-in-your-app-fdd2b9ed43c3
* https://tools.ietf.org/html/rfc4226
* https://tools.ietf.org/html/rfc6238
* https://github.com/google/google-authenticator/wiki/Key-Uri-Format
* https://security.stackexchange.com/questions/35157/how-does-google-authenticator-work
* https://github.com/robbiev/two-factor-auth/blob/master/main.go
* https://stefansundin.github.io/2fa-qr/


```bash
foo@bar:~$ virtualenv sandbox
foo@bar:~$ virtualenv -p $(which python3) sandbox
foo@bar:~$ source sandbox/bin/activate
foo@bar:~$ pip3 install --upgrade pip
foo@bar:~$ pip3 install -r requirements.txt
foo@bar:~$ python ./pass.py qr.png
foo@bar:~$ deactivate
```
58 changes: 58 additions & 0 deletions python3/pass.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
#!/bin/python3
import fastzbarlight
from PIL import Image
import time
import hmac
import hashlib
import urllib.parse as urlparse
import base64
import sys

if len(sys.argv) < 2:
print("Usage: python3 " + sys.argv[0] + " qr-code.png")
sys.exit(-1)

qr_code = fastzbarlight.scan_codes('qrcode', Image.open(sys.argv[1]))
qr_code = str(qr_code[0].decode())
print("QR code:", qr_code)

secret = None
digits = 6
period = 30
algo = hashlib.sha1
parsed = urlparse.urlparse(qr_code)
qs = urlparse.parse_qs(parsed.query)
for k,v in qs.items():
if k == "secret":
secret = v[0]
if k == "digits":
digits = int(v[0])
if k == "period":
period = int(v[0])
if k == "algorithm":
algo = getattr(hashlib, v[0].lower())
print("secret:", secret)
print("OTP length:", digits)
print("OTP lifetime:", period)

secret = base64.b32decode(secret)

currentUnixTime = int(time.time())
print("Unix time:", currentUnixTime)

counter = currentUnixTime // period
print("Counter:", counter)
counter = counter.to_bytes(8, byteorder = 'big')

hash = hmac.new(secret, counter, algo)
digest = hash.digest()
print("HMAC Digest", hash.hexdigest())

offset = digest[19] & 0xf # last nibble operations
print("offset:", offset)
truncatedHash = (digest[offset] & 0x7f) << 24 | (digest[offset+1] & 0xff) << 16 | (digest[offset+2] & 0xff) << 8 | (digest[offset+3] & 0xff)
print("truncatedHash:", hex(truncatedHash))
finalOTP = (truncatedHash % (10 ** digits))
print("finalOTP:", finalOTP)


Binary file added python3/qr.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
2 changes: 2 additions & 0 deletions python3/requirements.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
fastzbarlight==0.0.14
urlparse2==1.1.1