mirror of
https://github.com/RfidResearchGroup/RFIDtools.git
synced 2026-05-12 11:19:59 -07:00
module from github to local files.
This commit is contained in:
@@ -0,0 +1,62 @@
|
||||
# Built application files
|
||||
*.apk
|
||||
*.ap_
|
||||
|
||||
# Files for the ART/Dalvik VM
|
||||
*.dex
|
||||
|
||||
# Java class files
|
||||
*.class
|
||||
|
||||
# Generated files
|
||||
bin/
|
||||
gen/
|
||||
out/
|
||||
|
||||
# Cmake gen
|
||||
.cxx/
|
||||
|
||||
# Gradle files
|
||||
.gradle/
|
||||
build/
|
||||
|
||||
# Local configuration file (sdk path, etc)
|
||||
local.properties
|
||||
|
||||
# Proguard folder generated by Eclipse
|
||||
proguard/
|
||||
|
||||
# Log Files
|
||||
*.log
|
||||
|
||||
# Android Studio Navigation editor temp files
|
||||
.navigation/
|
||||
|
||||
# Android Studio captures folder
|
||||
captures/
|
||||
|
||||
# IntelliJ
|
||||
*.iml
|
||||
.idea/
|
||||
|
||||
# Keystore files
|
||||
# Uncomment the following line if you do not want to check your keystore files in.
|
||||
#*.jks
|
||||
|
||||
# External native build folder generated in Android Studio 2.2 and later
|
||||
.externalNativeBuild
|
||||
|
||||
# Google Services (e.g. APIs or Firebase)
|
||||
google-services.json
|
||||
|
||||
# Freeline
|
||||
freeline.py
|
||||
freeline/
|
||||
freeline_project_description.json
|
||||
|
||||
# fastlane
|
||||
fastlane/report.xml
|
||||
fastlane/Preview.html
|
||||
fastlane/screenshots
|
||||
fastlane/test_output
|
||||
fastlane/readme.md
|
||||
@@ -0,0 +1,33 @@
|
||||
apply plugin: 'com.android.library'
|
||||
apply plugin: 'com.github.dcendents.android-maven'
|
||||
group = 'com.github.xianglin1998'
|
||||
version = '1.0'
|
||||
|
||||
android {
|
||||
compileSdkVersion 29
|
||||
buildToolsVersion "29.0.3"
|
||||
|
||||
defaultConfig {
|
||||
minSdkVersion 19
|
||||
targetSdkVersion 29
|
||||
versionCode 1
|
||||
versionName "1.0"
|
||||
}
|
||||
|
||||
buildTypes {
|
||||
release {
|
||||
minifyEnabled false
|
||||
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
|
||||
}
|
||||
debug {
|
||||
minifyEnabled false
|
||||
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
dependencies {
|
||||
implementation fileTree(dir: 'libs', include: ['*.jar'])
|
||||
implementation 'androidx.appcompat:appcompat:1.1.0'
|
||||
}
|
||||
Vendored
+21
@@ -0,0 +1,21 @@
|
||||
# Add project specific ProGuard rules here.
|
||||
# You can control the set of applied configuration files using the
|
||||
# proguardFiles setting in build.gradle.
|
||||
#
|
||||
# For more details, see
|
||||
# http://developer.android.com/guide/developing/tools/proguard.html
|
||||
|
||||
# If your project uses WebView with JS, uncomment the following
|
||||
# and specify the fully qualified class name to the JavaScript interface
|
||||
# class:
|
||||
#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
|
||||
# public *;
|
||||
#}
|
||||
|
||||
# Uncomment this to preserve the line number information for
|
||||
# debugging stack traces.
|
||||
#-keepattributes SourceFile,LineNumberTable
|
||||
|
||||
# If you keep the line number information, uncomment this to
|
||||
# hide the original source file name.
|
||||
#-renamesourcefileattribute SourceFile
|
||||
@@ -0,0 +1,2 @@
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
package="cn.rrg.console" />
|
||||
@@ -0,0 +1,24 @@
|
||||
package cn.rrg.console.define;
|
||||
|
||||
/*
|
||||
* 定义命令行程序的接口!
|
||||
* */
|
||||
public interface ICommandTools {
|
||||
/**
|
||||
* 执行一个命令,根据传入的参数!
|
||||
* @param cmd 命令行,需要被执行的命令
|
||||
* @return 程序执行命令可能返回的值
|
||||
* */
|
||||
int startExecute(String cmd);
|
||||
|
||||
/*
|
||||
* 当前是否在执行当中!
|
||||
* @return 是否在运行当中,true or false
|
||||
* */
|
||||
boolean isExecuting();
|
||||
|
||||
/*
|
||||
* 停止一个当前正在执行的命令!
|
||||
* */
|
||||
void stopExecute();
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
package cn.rrg.console.define;
|
||||
|
||||
/*
|
||||
* 类型,对于控制台输出,可能有,1、密钥,2、数据,3、普通文本
|
||||
* */
|
||||
public interface ICommandType {
|
||||
//是一个密钥
|
||||
boolean isKey(String output);
|
||||
|
||||
//该怎么解析
|
||||
String parseKey(String output);
|
||||
|
||||
//是一段数据
|
||||
boolean isData(String output);
|
||||
|
||||
//该怎么解析
|
||||
String parseData(String output);
|
||||
|
||||
//是普通文本
|
||||
boolean isText(String output);
|
||||
|
||||
//该怎么解析
|
||||
Runnable parseText(String output);
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
<resources>
|
||||
<string name="app_name">console</string>
|
||||
</resources>
|
||||
@@ -0,0 +1,62 @@
|
||||
# Built application files
|
||||
*.apk
|
||||
*.ap_
|
||||
|
||||
# Files for the ART/Dalvik VM
|
||||
*.dex
|
||||
|
||||
# Java class files
|
||||
*.class
|
||||
|
||||
# Generated files
|
||||
bin/
|
||||
gen/
|
||||
out/
|
||||
|
||||
# Cmake gen
|
||||
.cxx/
|
||||
|
||||
# Gradle files
|
||||
.gradle/
|
||||
build/
|
||||
|
||||
# Local configuration file (sdk path, etc)
|
||||
local.properties
|
||||
|
||||
# Proguard folder generated by Eclipse
|
||||
proguard/
|
||||
|
||||
# Log Files
|
||||
*.log
|
||||
|
||||
# Android Studio Navigation editor temp files
|
||||
.navigation/
|
||||
|
||||
# Android Studio captures folder
|
||||
captures/
|
||||
|
||||
# IntelliJ
|
||||
*.iml
|
||||
.idea/
|
||||
|
||||
# Keystore files
|
||||
# Uncomment the following line if you do not want to check your keystore files in.
|
||||
#*.jks
|
||||
|
||||
# External native build folder generated in Android Studio 2.2 and later
|
||||
.externalNativeBuild
|
||||
|
||||
# Google Services (e.g. APIs or Firebase)
|
||||
google-services.json
|
||||
|
||||
# Freeline
|
||||
freeline.py
|
||||
freeline/
|
||||
freeline_project_description.json
|
||||
|
||||
# fastlane
|
||||
fastlane/report.xml
|
||||
fastlane/Preview.html
|
||||
fastlane/screenshots
|
||||
fastlane/test_output
|
||||
fastlane/readme.md
|
||||
@@ -0,0 +1,41 @@
|
||||
apply plugin: 'com.android.library'
|
||||
apply plugin: 'com.github.dcendents.android-maven'
|
||||
group = 'com.github.xianglin1998'
|
||||
version = '1.3'
|
||||
|
||||
android {
|
||||
compileSdkVersion 29
|
||||
buildToolsVersion "29.0.2"
|
||||
|
||||
defaultConfig {
|
||||
minSdkVersion 19
|
||||
targetSdkVersion 29
|
||||
externalNativeBuild {
|
||||
cmake {
|
||||
arguments '-DANDROID_STL=c++_static'
|
||||
abiFilters "x86", "x86_64", "armeabi-v7a", "arm64-v8a"
|
||||
}
|
||||
//abiFilters "armeabi"
|
||||
/*abiFilters "arm64-v8a"*/
|
||||
/*abiFilters "x86_64"*/
|
||||
/*abiFilters "arm64-v8a"
|
||||
abiFilters "mips"
|
||||
abiFilters "mips64"
|
||||
abiFilters "x86"
|
||||
abiFilters "x86_64"*/
|
||||
}
|
||||
}
|
||||
externalNativeBuild {
|
||||
cmake {
|
||||
version '3.10.2'
|
||||
path 'src/main/cpp/CMakeLists.txt'
|
||||
}
|
||||
}
|
||||
|
||||
buildTypes {
|
||||
release {
|
||||
minifyEnabled false
|
||||
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
|
||||
}
|
||||
}
|
||||
}
|
||||
Vendored
+21
@@ -0,0 +1,21 @@
|
||||
# Add project specific ProGuard rules here.
|
||||
# You can control the set of applied configuration files using the
|
||||
# proguardFiles setting in build.gradle.
|
||||
#
|
||||
# For more details, see
|
||||
# http://developer.android.com/guide/developing/tools/proguard.html
|
||||
|
||||
# If your project uses WebView with JS, uncomment the following
|
||||
# and specify the fully qualified class name to the JavaScript interface
|
||||
# class:
|
||||
#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
|
||||
# public *;
|
||||
#}
|
||||
|
||||
# Uncomment this to preserve the line number information for
|
||||
# debugging stack traces.
|
||||
#-keepattributes SourceFile,LineNumberTable
|
||||
|
||||
# If you keep the line number information, uncomment this to
|
||||
# hide the original source file name.
|
||||
#-renamesourcefileattribute SourceFile
|
||||
@@ -0,0 +1,2 @@
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
package="cn.dxl.crapto1" />
|
||||
@@ -0,0 +1,19 @@
|
||||
#需要的最cmake版本
|
||||
cmake_minimum_required(VERSION 3.4.1)
|
||||
|
||||
#进行库(动态)的添加,在之后的参数中引入cpp/c文件
|
||||
add_library(
|
||||
crapto1 SHARED
|
||||
crapto1.c
|
||||
crypto1.c
|
||||
main.c)
|
||||
|
||||
#进行头文件的添加!
|
||||
target_include_directories(crapto1 PRIVATE
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/include)
|
||||
|
||||
#进行最终动态库的链接!
|
||||
target_link_libraries(
|
||||
crapto1
|
||||
android
|
||||
log)
|
||||
@@ -0,0 +1,251 @@
|
||||
#include <stdlib.h>
|
||||
#include "crapto1.h"
|
||||
#include "crypto1.h"
|
||||
|
||||
#pragma package(smart_init)
|
||||
#if !defined LOWMEM && defined __GNUC__
|
||||
static uint8_t filterlut[1 << 20];
|
||||
|
||||
static void __attribute__((constructor)) fill_lut() {
|
||||
uint32_t i;
|
||||
for (i = 0; i < 1 << 20; ++i)
|
||||
filterlut[i] = filter(i);
|
||||
}
|
||||
|
||||
#define filter(x) (filterlut[(x) & 0xfffff])
|
||||
#endif
|
||||
|
||||
/* quicksort
|
||||
* in place quicksort of table
|
||||
*/
|
||||
static void
|
||||
quicksort(uint32_t *const start, uint32_t *const stop) {
|
||||
uint32_t *it = start + 1, *rit = stop;
|
||||
|
||||
if (it > rit)
|
||||
return;
|
||||
|
||||
while (it < rit)
|
||||
if (*it < *start)
|
||||
++it;
|
||||
else if (*rit >= *start)
|
||||
--rit;
|
||||
else
|
||||
*it ^= (*it ^= *rit, *rit ^= *it);
|
||||
|
||||
if (*rit >= *start)
|
||||
--rit;
|
||||
if (rit != start)
|
||||
*rit ^= (*rit ^= *start, *start ^= *rit);
|
||||
|
||||
quicksort(start, rit - 1);
|
||||
quicksort(rit + 1, stop);
|
||||
}
|
||||
|
||||
/* binsearch
|
||||
* Binary search for the first occurence of *stop's MSB in sorted [start,stop]
|
||||
*/
|
||||
static inline uint32_t *
|
||||
binsearch(uint32_t *start, uint32_t *stop) {
|
||||
uint32_t mid, val = *stop & 0xff000000;
|
||||
while (start != stop)
|
||||
if (start[mid = (stop - start) >> 1] > val)
|
||||
stop = &start[mid];
|
||||
else
|
||||
start += mid + 1;
|
||||
|
||||
return start;
|
||||
}
|
||||
|
||||
/* update_contribution
|
||||
* helper, calculates the partial linear feedback contributions and puts in MSB
|
||||
*/
|
||||
static inline void
|
||||
update_contribution(uint32_t *item, const uint32_t mask1, const uint32_t mask2) {
|
||||
uint32_t p = *item >> 25;
|
||||
|
||||
p = p << 1 | parity(*item & mask1);
|
||||
p = p << 1 | parity(*item & mask2);
|
||||
*item = p << 24 | (*item & 0xffffff);
|
||||
}
|
||||
|
||||
/* extend_table
|
||||
* using a bit of the keystream extend the table of possible lfsr states
|
||||
*/
|
||||
static inline void
|
||||
extend_table(uint32_t *tbl, uint32_t **end, int bit, uint32_t m1, uint32_t m2) {
|
||||
for (; tbl <= *end; tbl++)
|
||||
if (filter(*tbl <<= 1) == bit) {
|
||||
if (filter(*tbl | 1) == bit) {
|
||||
*++*end = tbl[1];
|
||||
tbl[1] = tbl[0] | 1;
|
||||
update_contribution(tbl++, m1, m2);
|
||||
}
|
||||
update_contribution(tbl, m1, m2);
|
||||
} else if (filter(*tbl |= 1) == bit)
|
||||
update_contribution(tbl, m1, m2);
|
||||
else
|
||||
*tbl-- = *(*end)--;
|
||||
}
|
||||
|
||||
|
||||
/* recover
|
||||
* recursively narrow down the search space, 4 bits of keystream at a time
|
||||
*/
|
||||
static uint32_t *
|
||||
recover(uint32_t *o_head, uint32_t *o_tail, uint32_t oks,
|
||||
uint32_t *e_head, uint32_t *e_tail, uint32_t eks, int rem) {
|
||||
uint32_t *o, *e, i;
|
||||
|
||||
if (rem == -1) {
|
||||
o_head[1] = *e_head << 1;
|
||||
*e_head &= LF_POLY_EVEN;
|
||||
o_head[1] |= parity(*e_head ^ *o_head & LF_POLY_ODD);
|
||||
return o_head;
|
||||
}
|
||||
|
||||
for (i = 0; i < 4 && rem--; i++) {
|
||||
extend_table(o_head, &o_tail, (oks >>= 1) & 1, LF_POLY_ODD * 2, LF_POLY_EVEN * 2 + 1);
|
||||
extend_table(e_head, &e_tail, (eks >>= 1) & 1, LF_POLY_EVEN * 2 + 1, LF_POLY_ODD);
|
||||
}
|
||||
|
||||
quicksort(o_head, o_tail);
|
||||
quicksort(e_head, e_tail);
|
||||
|
||||
while (o_tail >= o_head && e_tail >= e_head)
|
||||
if ((*o_tail ^ *e_tail) >> 24 == 0) {
|
||||
o_tail = binsearch(o_head, o = o_tail);
|
||||
e_tail = binsearch(e_head, e = e_tail);
|
||||
if (e = recover(o_tail--, o, oks, e_tail--, e, eks, rem))
|
||||
return e;
|
||||
} else if (*o_tail > *e_tail)
|
||||
--o_tail;
|
||||
else
|
||||
--e_tail;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* lfsr_recovery
|
||||
* recover the state of the lfsr given a part of the keystream
|
||||
*/
|
||||
struct Crypto1State *lfsr_recovery(uint32_t ks2, uint32_t ks3) {
|
||||
uint32_t *odd_head = 0, *odd_tail = 0, oks = 0;
|
||||
uint32_t *even_head = 0, *even_tail = 0, eks = 0, *res;
|
||||
|
||||
struct Crypto1State *state = crypto1_create(-1);
|
||||
int i;
|
||||
|
||||
for (i = 31; i >= 0; i -= 2)
|
||||
oks = oks << 1 | BEBIT(ks2, i) | BEBIT(ks3, i) << 16;
|
||||
for (i = 30; i >= 0; i -= 2)
|
||||
eks = eks << 1 | BEBIT(ks2, i) | BEBIT(ks3, i) << 16;
|
||||
|
||||
|
||||
odd_head = odd_tail = (uint32_t *) malloc(sizeof(uint32_t) << 21);
|
||||
even_head = even_tail = (uint32_t *) malloc(sizeof(uint32_t) << 21);
|
||||
if (!odd_tail-- || !even_tail--)
|
||||
goto out;
|
||||
|
||||
for (i = 1 << 20; i >= 0; --i) {
|
||||
if (filter(i) == (oks & 1))
|
||||
*++odd_tail = i;
|
||||
if (filter(i) == (eks & 1))
|
||||
*++even_tail = i;
|
||||
}
|
||||
|
||||
for (i = 0; i < 4; i++) {
|
||||
extend_table(odd_head, &odd_tail, (oks >>= 1) & 1, 0, 0);
|
||||
extend_table(even_head, &even_tail, (eks >>= 1) & 1, 0, 0);
|
||||
}
|
||||
|
||||
res = recover(odd_head, odd_tail, oks, even_head, even_tail, eks, 27);
|
||||
|
||||
if (res) {
|
||||
state->odd = res[1];
|
||||
state->even = res[0];
|
||||
}
|
||||
out:
|
||||
free(odd_head);
|
||||
free(even_head);
|
||||
return state;
|
||||
}
|
||||
|
||||
/* Variation mentioned in the paper. Borked due to omitted constants.
|
||||
* comform the above version given 64 bits of keystream, it returns a possible
|
||||
* cipher state if any.
|
||||
* It can be optimized dramatically but since it was borked a somewhat readable
|
||||
* and above all short version is included.
|
||||
*/
|
||||
#define MAGIX1 (0)
|
||||
#define MAGIX2 (0) /* Well this number isn't that magical ... */
|
||||
|
||||
struct Crypto1State *lfsr_recovery_borked(uint32_t ks2, uint32_t ks3) {
|
||||
struct Crypto1State *state = crypto1_create(-1);
|
||||
uint32_t win = 0, oks = 0, eks = 0, tes, tos;
|
||||
uint64_t cmb, *table = (uint64_t *) malloc(1 << 25), *tail = table - 1, *tbl;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < 32; i += 2)
|
||||
oks = oks << 1 | BEBIT(ks3, i) | BEBIT(ks2, i) << 16;
|
||||
for (i = 1; i < 32; i += 2)
|
||||
eks = eks << 1 | BEBIT(ks3, i) | BEBIT(ks2, i) << 16;
|
||||
|
||||
for (i = 0; i < 1 << 20; ++i)
|
||||
if (filter(i) == BIT(oks, 31))
|
||||
*++tail = i;
|
||||
|
||||
for (i = 30; i > 2; --i)
|
||||
for (*(tbl = table) <<= 1; tbl <= tail; *++tbl <<= 1)
|
||||
if (filter(*tbl) ^ filter(*tbl | 1))
|
||||
*tbl |= (filter(*tbl) != BIT(oks, i));
|
||||
else if (filter(*tbl) == BIT(oks, i)) {
|
||||
*++tail = *++tbl;
|
||||
*tbl = tbl[-1] | 1;
|
||||
} else
|
||||
*tbl-- = *tail--;
|
||||
|
||||
for (; tail >= table; --tail) {
|
||||
cmb = MAGIX1;
|
||||
for (i = 0; i < 51; ++i) {
|
||||
win = win << 1 ^ par64(*tail & cmb);
|
||||
tes = tes << 1 ^ filter(win);
|
||||
cmb = cmb >> 1 ^ -(cmb & 1) & MAGIX2;
|
||||
}
|
||||
|
||||
for (i = 2; i >= 0; --i) {
|
||||
*tail = *tail << 1 | par64(*tail & MAGIX2);
|
||||
tos = tos << 1 | filter(*tail);
|
||||
}
|
||||
|
||||
if (tes == eks && (tos & 7) == (oks & 7)) {
|
||||
state->odd = *tail << 1 | par64(*tail & MAGIX2);
|
||||
state->even = win;
|
||||
}
|
||||
}
|
||||
|
||||
free(table);
|
||||
return state;
|
||||
}
|
||||
|
||||
/* lfsr_rollback
|
||||
* Rollback the shift register in order to get previous states
|
||||
*/
|
||||
void lfsr_rollback(struct Crypto1State *s, uint32_t in, int fb) {
|
||||
int i, out;
|
||||
|
||||
s->odd &= 0xffffff;
|
||||
s->even &= 0xffffff;
|
||||
for (i = 31; i >= 0; --i) {
|
||||
s->odd ^= (s->odd ^= s->even, s->even ^= s->odd);
|
||||
|
||||
out = s->even & 1;
|
||||
out ^= LF_POLY_EVEN & (s->even >>= 1);
|
||||
out ^= LF_POLY_ODD & s->odd;
|
||||
out ^= BEBIT(in, i);
|
||||
out ^= filter(s->odd) & !!fb;
|
||||
|
||||
s->even |= parity(out) << 23;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,90 @@
|
||||
/* crypto1.c
|
||||
|
||||
This program is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public License
|
||||
as published by the Free Software Foundation; either version 2
|
||||
of the License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
|
||||
MA 02110-1301, US
|
||||
|
||||
Copyright (C) 2008-2008 bla <blapost@gmail.com>
|
||||
*/
|
||||
#include "crapto1.h"
|
||||
#include <stdlib.h>
|
||||
|
||||
#define SWAPENDIAN(x)\
|
||||
(x = (x >> 8 & 0xff00ff) | (x & 0xff00ff) << 8, x = x >> 16 | x << 16)
|
||||
|
||||
struct Crypto1State *crypto1_create(uint64_t key) {
|
||||
struct Crypto1State *s = malloc(sizeof(*s));
|
||||
int i;
|
||||
for (i = 47; s && i > 0; i -= 2) {
|
||||
s->odd = s->odd << 1 | BIT(key, (i - 1) ^ 7);
|
||||
s->even = s->even << 1 | BIT(key, i ^ 7);
|
||||
}
|
||||
return s;
|
||||
}
|
||||
|
||||
void crypto1_destroy(struct Crypto1State *state) {
|
||||
free(state);
|
||||
}
|
||||
|
||||
void crypto1_get_lfsr(struct Crypto1State *state, uint64_t *lfsr) {
|
||||
int i;
|
||||
for (*lfsr = 0, i = 23; i >= 0; --i) {
|
||||
*lfsr = *lfsr << 1 | BIT(state->odd, i ^ 3);
|
||||
*lfsr = *lfsr << 1 | BIT(state->even, i ^ 3);
|
||||
}
|
||||
}
|
||||
|
||||
uint8_t crypto1_bit(struct Crypto1State *s, uint8_t in, int is_encrypted) {
|
||||
uint32_t feedin;
|
||||
uint8_t ret = filter(s->odd);
|
||||
|
||||
feedin = ret & !!is_encrypted;
|
||||
feedin ^= !!in;
|
||||
feedin ^= LF_POLY_ODD & s->odd;
|
||||
feedin ^= LF_POLY_EVEN & s->even;
|
||||
s->even = s->even << 1 | parity(feedin);
|
||||
|
||||
s->odd ^= (s->odd ^= s->even, s->even ^= s->odd);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
uint8_t crypto1_byte(struct Crypto1State *s, uint8_t in, int is_encrypted) {
|
||||
uint8_t i, ret = 0;
|
||||
|
||||
for (i = 0; i < 8; ++i)
|
||||
ret |= crypto1_bit(s, BIT(in, i), is_encrypted) << i;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
uint32_t crypto1_word(struct Crypto1State *s, uint32_t in, int is_encrypted) {
|
||||
uint32_t i, ret = 0;
|
||||
|
||||
for (i = 0; i < 32; ++i)
|
||||
ret |= crypto1_bit(s, BEBIT(in, i), is_encrypted) << (i ^ 24);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* prng_successor
|
||||
* helper used to obscure the keystream during authentication
|
||||
*/
|
||||
uint32_t prng_successor(uint32_t x, uint32_t n) {
|
||||
SWAPENDIAN(x);
|
||||
while (n--)
|
||||
x = x >> 1 | (x >> 16 ^ x >> 18 ^ x >> 19 ^ x >> 21) << 31;
|
||||
|
||||
return SWAPENDIAN(x);
|
||||
}
|
||||
@@ -0,0 +1,57 @@
|
||||
//---------------------------------------------------------------------------
|
||||
|
||||
#ifndef crapto1H
|
||||
#define crapto1H
|
||||
//---------------------------------------------------------------------------
|
||||
#include "crypto1.h"
|
||||
#include <stdint.h>
|
||||
|
||||
struct Crypto1State {
|
||||
unsigned int odd, even;
|
||||
};
|
||||
|
||||
struct Crypto1State *crypto1_create(uint64_t key);
|
||||
|
||||
void crypto1_destroy(struct Crypto1State *state);
|
||||
|
||||
void crypto1_get_lfsr(struct Crypto1State *state, uint64_t *lfsr);
|
||||
|
||||
unsigned int crypto1_word(struct Crypto1State *state, unsigned int in_word, int fb);
|
||||
|
||||
unsigned int prng_successor(unsigned int x, unsigned int n);
|
||||
|
||||
struct Crypto1State *lfsr_recovery(unsigned int ks2, unsigned int ks3);
|
||||
|
||||
struct Crypto1State *lfsr_recovery_borked(unsigned int ks2, unsigned int ks3);
|
||||
|
||||
void lfsr_rollback(struct Crypto1State *s, unsigned int in, int fb);
|
||||
|
||||
#define LF_POLY_ODD (0x29CE5C)
|
||||
#define LF_POLY_EVEN (0x870804)
|
||||
#define BIT(x, n) ((x) >> (n) & 1)
|
||||
#define BEBIT(x, n) ((x) >> ((n) ^ 24) & 1)
|
||||
|
||||
static inline int parity(unsigned int x) {
|
||||
x ^= x >> 16;
|
||||
x ^= x >> 8;
|
||||
x ^= x >> 4;
|
||||
return BIT(0x6996, x & 0xf);
|
||||
}
|
||||
|
||||
static inline int par64(uint64_t x) {
|
||||
return parity(x ^ x >> 32);
|
||||
}
|
||||
|
||||
static inline int filter(unsigned int const x) {
|
||||
unsigned int f;
|
||||
|
||||
f = 0xf22c0 >> (x & 0xf) & 16;
|
||||
f |= 0x6c9c0 >> (x >> 4 & 0xf) & 8;
|
||||
f |= 0x3c8b0 >> (x >> 8 & 0xf) & 4;
|
||||
f |= 0x1e458 >> (x >> 12 & 0xf) & 2;
|
||||
f |= 0x0d938 >> (x >> 16 & 0xf) & 1;
|
||||
return BIT(0xEC57E80A, f);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
@@ -0,0 +1,19 @@
|
||||
//---------------------------------------------------------------------------
|
||||
#ifndef crypto1H
|
||||
#define crypto1H
|
||||
//---------------------------------------------------------------------------
|
||||
#include "crapto1.h"
|
||||
#include <stdlib.h>
|
||||
|
||||
struct Crypto1State *crypto1_create(uint64_t key);
|
||||
|
||||
void crypto1_destroy(struct Crypto1State *state);
|
||||
|
||||
void crypto1_get_lfsr(struct Crypto1State *state, uint64_t *lfsr);
|
||||
|
||||
unsigned int crypto1_word(struct Crypto1State *s, unsigned int in_word, int fb);
|
||||
|
||||
unsigned int prng_successor(unsigned int x, unsigned int n);
|
||||
|
||||
#endif
|
||||
|
||||
@@ -0,0 +1,183 @@
|
||||
#include <stdbool.h>
|
||||
#include <ctype.h>
|
||||
#include <inttypes.h>
|
||||
#include <crapto1.h>
|
||||
#include <stdio.h>
|
||||
#include <malloc.h>
|
||||
#include <string.h>
|
||||
#include <jni.h>
|
||||
|
||||
//转为小写字符串!
|
||||
char *strupr(char *str) {
|
||||
char *ret = str;
|
||||
char *tmp = ret;
|
||||
//测试长度!
|
||||
size_t len = strlen(tmp);
|
||||
while (len != 0 && tmp != NULL) {
|
||||
*str = (char) toupper(*tmp);
|
||||
--len;
|
||||
++tmp;
|
||||
++str;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
struct CHexMap {
|
||||
char chr;
|
||||
int value;
|
||||
};
|
||||
const int HexMapL = 16;
|
||||
struct CHexMap HexMap[HexMapL] = {
|
||||
{'0', 0},
|
||||
{'1', 1},
|
||||
{'2', 2},
|
||||
{'3', 3},
|
||||
{'4', 4},
|
||||
{'5', 5},
|
||||
{'6', 6},
|
||||
{'7', 7},
|
||||
{'8', 8},
|
||||
{'9', 9},
|
||||
{'A', 10},
|
||||
{'B', 11},
|
||||
{'C', 12},
|
||||
{'D', 13},
|
||||
{'E', 14},
|
||||
{'F', 15}
|
||||
};
|
||||
|
||||
//16进制字符串转整形!
|
||||
uint32_t httoi(const char *value) {
|
||||
//拷贝一份新的!
|
||||
char *newCs = strdup(value);
|
||||
char *s = strupr(newCs);;
|
||||
uint32_t result = 0;
|
||||
if (*s == '0' && *(s + 1) == 'X') s += 2;
|
||||
bool firsttime = true;
|
||||
while (*s != '\0') {
|
||||
bool found = false;
|
||||
for (int i = 0; i < HexMapL; i++) {
|
||||
if (*s == HexMap[i].chr) {
|
||||
if (!firsttime) result <<= 4;
|
||||
result |= HexMap[i].value;
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!found) break;
|
||||
s++;
|
||||
firsttime = false;
|
||||
}
|
||||
//LOGD("尝试输出字符值: %s", mstr);
|
||||
free(newCs);
|
||||
return result;
|
||||
}
|
||||
|
||||
//主函数,进行最终的线性反馈寄存器算法回滚!
|
||||
uint64_t finalKey(const char *id, const char *tc, const char *rc, const char *rr, const char *tr) {
|
||||
struct Crypto1State *revstate;
|
||||
uint64_t lfsr;
|
||||
//获得输入框得UID
|
||||
uint32_t uid = httoi(id);
|
||||
//LOGD("测试输出ID : %u", uid);
|
||||
//获得TAG得收集信息!
|
||||
uint32_t tag_challenge = httoi(tc);
|
||||
//LOGD("测试输出TC : %u", tag_challenge);
|
||||
//获得ENC
|
||||
uint32_t nr_enc = httoi(rc);
|
||||
//LOGD("测试输出RC : %u", nr_enc);
|
||||
//获得来自于读卡器得应答
|
||||
uint32_t reader_response = httoi(rr);
|
||||
//LOGD("测试输出RR : %u", reader_response);
|
||||
//获得来自于标签得应答
|
||||
uint32_t tag_response = httoi(tr);
|
||||
//LOGD("测试输出TR : %u", tag_response);
|
||||
//进行ks计算
|
||||
uint32_t ks2 = reader_response ^prng_successor(tag_challenge, 64);
|
||||
uint32_t ks3 = tag_response ^prng_successor(tag_challenge, 96);
|
||||
//调用线性反馈寄存器关键函数进行计算
|
||||
revstate = lfsr_recovery(ks2, ks3);
|
||||
//尝试回滚
|
||||
lfsr_rollback(revstate, 0, 0);
|
||||
//第二次尝试回滚
|
||||
lfsr_rollback(revstate, 0, 0);
|
||||
//通过nr尝试回滚
|
||||
lfsr_rollback(revstate, nr_enc, 1);
|
||||
//通过uid与关键信息进行回滚
|
||||
lfsr_rollback(revstate, uid ^ tag_challenge, 0);
|
||||
//得到关键密钥
|
||||
crypto1_get_lfsr(revstate, &lfsr);
|
||||
//回收内存!
|
||||
crypto1_destroy(revstate);
|
||||
//返回最终结果
|
||||
return lfsr;
|
||||
}
|
||||
|
||||
//映射函数,两端映射,类型转换!
|
||||
jstring
|
||||
final(JNIEnv *env, jobject instance, jstring hexID, jstring hexTC, jstring hexRC, jstring hexRR,
|
||||
jstring hexTR) {
|
||||
if (hexID == NULL || hexTC == NULL || hexRC == NULL || hexRR == NULL || hexTR == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
jboolean isCopy = false;
|
||||
//获得字符数组!
|
||||
const char *id = (*env)->GetStringUTFChars(env, hexID, &isCopy);
|
||||
//const jint idLen = (*env)->GetStringUTFLength(env, hexID);
|
||||
// LOGD("final ID: %s", id);
|
||||
const char *tc = (*env)->GetStringUTFChars(env, hexTC, &isCopy);
|
||||
//const jint tcLen = (*env)->GetStringUTFLength(env, hexTC);
|
||||
//LOGD("final TC: %s", tc);
|
||||
const char *rc = (*env)->GetStringUTFChars(env, hexRC, &isCopy);
|
||||
//const jint rcLen = (*env)->GetStringUTFLength(env, hexRC);
|
||||
//LOGD("final RC: %s", rc);
|
||||
const char *rr = (*env)->GetStringUTFChars(env, hexRR, &isCopy);
|
||||
//const jint rrLen = (*env)->GetStringUTFLength(env, hexRR);
|
||||
//LOGD("final RR: %s", rr);
|
||||
const char *tr = (*env)->GetStringUTFChars(env, hexTR, &isCopy);
|
||||
//const jint trLen = (*env)->GetStringUTFLength(env, hexTR);
|
||||
//LOGD("final TR: %s", tr);
|
||||
//调用主要的逻辑函数,进行计算!
|
||||
uint64_t key = finalKey(id, tc, rc, rr, tr);
|
||||
//谨记释放!
|
||||
(*env)->ReleaseStringUTFChars(env, hexID, id);
|
||||
(*env)->ReleaseStringUTFChars(env, hexTC, tc);
|
||||
(*env)->ReleaseStringUTFChars(env, hexRC, rc);
|
||||
(*env)->ReleaseStringUTFChars(env, hexRR, rr);
|
||||
(*env)->ReleaseStringUTFChars(env, hexTR, tr);
|
||||
//进行格式化转换!
|
||||
char keyChars[13] = {0};
|
||||
memset(keyChars, 0, sizeof(keyChars));
|
||||
sprintf(keyChars, "%012"PRIX64, key);
|
||||
//LOGD("输出测试的64位值: %lu", key);
|
||||
//LOGD("输出测试的密钥: %s", keyChars);
|
||||
return (*env)->NewStringUTF(env, keyChars);
|
||||
}
|
||||
|
||||
/*
|
||||
* jvm加载so时的映射回调
|
||||
* */
|
||||
JNIEXPORT jint JNI_OnLoad(JavaVM *vm, void *reserved) {
|
||||
JNIEnv *jniEnv = NULL;
|
||||
//得到当前的jvm环境指针
|
||||
if ((*vm)->GetEnv(vm, (void **) &jniEnv, JNI_VERSION_1_4) != JNI_OK) {
|
||||
return -1;
|
||||
}
|
||||
//得到native函数的定义类
|
||||
jclass clazz = (*jniEnv)->FindClass(jniEnv, "cn/dxl/crapto1/Crapto1");
|
||||
if (clazz == NULL) {
|
||||
return -1;
|
||||
}
|
||||
//构建和初始化函数结构体,分别是java层的函数名称,签名,对应的函数指针
|
||||
JNINativeMethod methods[] = {
|
||||
{"finalKeyNative", "(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String;", (void *) final},
|
||||
};
|
||||
//注册函数
|
||||
if ((*jniEnv)->RegisterNatives(jniEnv, clazz, methods,
|
||||
sizeof(methods) / sizeof(methods[0])) !=
|
||||
JNI_OK) {
|
||||
return -1;
|
||||
}
|
||||
//最后一定要返回jni的版本。
|
||||
return JNI_VERSION_1_4;
|
||||
}
|
||||
@@ -0,0 +1,62 @@
|
||||
package cn.dxl.crapto1;
|
||||
|
||||
/*
|
||||
* 此class用于crapto1算法的回滚计算!
|
||||
* */
|
||||
public class Crapto1 {
|
||||
|
||||
static {
|
||||
//加载动态库!
|
||||
System.loadLibrary("crapto1");
|
||||
}
|
||||
|
||||
private String mHexId = null;
|
||||
private String mHexTC = null;
|
||||
private String mHexRC = null;
|
||||
private String mHexRR = null;
|
||||
private String mHexTR = null;
|
||||
|
||||
public Crapto1 setUid(String hexID) {
|
||||
mHexId = hexID;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Crapto1 setTagChallenge(String hexTC) {
|
||||
mHexTC = hexTC;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Crapto1 setReaderChallenge(String hexRC) {
|
||||
mHexRC = hexRC;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Crapto1 setReaderResponse(String hexRR) {
|
||||
mHexRR = hexRR;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Crapto1 setTagResponse(String hexTR) {
|
||||
mHexTR = hexTR;
|
||||
return this;
|
||||
}
|
||||
|
||||
public String finalKey() {
|
||||
//非空判定!
|
||||
if (mHexId == null || mHexTC == null ||
|
||||
mHexRC == null || mHexRR == null || mHexTR == null)
|
||||
return null;
|
||||
//格式判定!
|
||||
if (invailV(mHexId) || invailV(mHexTC)
|
||||
|| invailV(mHexRC) || invailV(mHexRR) || invailV(mHexTR)) {
|
||||
return null;
|
||||
}
|
||||
return finalKeyNative(mHexId, mHexTC, mHexRC, mHexRR, mHexTR);
|
||||
}
|
||||
|
||||
private boolean invailV(String v) {
|
||||
return v.length() != 8 || !v.matches("[A-Za-z0-9]+");
|
||||
}
|
||||
|
||||
private native String finalKeyNative(String id, String tc, String rc, String rr, String tr);
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
<resources>
|
||||
<string name="app_name">Crapto1</string>
|
||||
</resources>
|
||||
@@ -0,0 +1 @@
|
||||
/build
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user