增加了tac
diff --git a/dlsmk/src/lib.rs b/dlsmk/src/lib.rs
index fa982de..709b240 100644
--- a/dlsmk/src/lib.rs
+++ b/dlsmk/src/lib.rs
@@ -1,9 +1,24 @@
+extern crate base64;
+extern crate hex;
+
#[cfg(test)]
mod tests {
#[test]
fn it_works() {
assert_eq!(2 + 2, 4);
}
+
+ #[test]
+ fn test_key() {
+ let key = "wDp3/3NPEi+R0peokVv010GkDk1mRTp3tUB/lCEVRAA=";
+ let key_buffer = base64::decode_config(key, base64::STANDARD).unwrap();
+ let s = hex::encode(key_buffer.as_slice());
+ let key_string = hex::decode(format!("{}{:04x}{:02x}", s, 30, 5)).unwrap();
+ println!(
+ "key : {}",
+ base64::encode_config(key_string, base64::URL_SAFE)
+ );
+ }
}
// use std::ffi::{CStr, CString};
@@ -18,20 +33,21 @@
// CString::new("Hello ".to_owned()).unwrap().into_raw()
// }
-// #[cfg(target_os = "android")]
#[cfg(any(target_family = "unix", target_os = "android"))]
-// #[cfg(target_family = "unix")]
#[allow(non_snake_case)]
pub mod android {
+ extern crate base64;
extern crate jni;
use self::jni::objects::{JClass, JMap, JObject, JString};
- use self::jni::sys::{jboolean, jlong, JNI_FALSE, JNI_TRUE};
+ use self::jni::sys::{jboolean, jint, jlong, JNI_FALSE, JNI_TRUE};
use self::jni::JNIEnv;
// use super::*;
use libc;
use std::slice;
+ use log::debug;
+
use dlqrcode::DaliQrCode;
fn put_data(env: &JNIEnv, map: &JMap, key: &str, value: &str) {
@@ -75,11 +91,17 @@
let qrdata = env.get_map(result).expect("invalid qrdata map");
- let key = {
+ let (key, step, skew) = {
let mut k = [0u8; 32];
- if let Ok(v) = hex::decode(key.as_slice()) {
- k.clone_from_slice(v.as_slice());
- k
+ if let Ok(v) = base64::decode_config(key.as_slice(), base64::URL_SAFE) {
+ if v.len() != 35 {
+ put_data(&env, &qrdata, "error", "key format error");
+ return JNI_FALSE;
+ }
+ k.clone_from_slice(&v.as_slice()[..32]);
+ let step = ((v[32] as u64) << 8) | (v[33] as u64);
+ let skew = v[34] as u8;
+ (k, step, skew)
} else {
put_data(
&env,
@@ -91,7 +113,8 @@
}
};
- let decode = match DaliQrCode::new(key, None, None, None, None) {
+ debug!("TOTP step <{}> , skew <{}>", step, skew);
+ let decoder = match DaliQrCode::new(key, None, Some(step), Some(skew), None) {
Ok(d) => d,
Err(e) => {
let s = format!("invalid input parameter {:?}", e);
@@ -100,26 +123,13 @@
}
};
- match decode.decode(qrcode.as_ptr(), qrcode.len(), offset as i32) {
+ match decoder.decode(qrcode.as_ptr(), qrcode.len(), offset as i32) {
Ok(d) => {
- qrdata
- .put(
- *env.new_string("cardno").unwrap(),
- *env.new_string(d.cardno).unwrap(),
- )
- .unwrap();
- qrdata
- .put(
- *env.new_string("cardtype").unwrap(),
- *env.new_string(d.cardtype).unwrap(),
- )
- .unwrap();
- qrdata
- .put(
- *env.new_string("uid").unwrap(),
- *env.new_string(d.uid).unwrap(),
- )
- .unwrap();
+ put_data(&env, &qrdata, "cardno", &d.cardno);
+ put_data(&env, &qrdata, "cardtype", &d.cardtype);
+ put_data(&env, &qrdata, "uid", &d.uid);
+ let sign = dlqrcode::transaction_sign(&d);
+ put_data(&env, &qrdata, "sign", &sign);
return JNI_TRUE;
}
Err(e) => {
@@ -129,4 +139,56 @@
}
};
}
+
+ #[no_mangle]
+ pub unsafe extern "C" fn Java_com_supwisdom_dlsmk_DLSMKQrCode_genTac(
+ env: JNIEnv,
+ _: JClass,
+ qrsign: JString,
+ cardno: JString,
+ amount: jint,
+ termDatetime: JString,
+ result: JObject,
+ ) -> jboolean {
+ let qrsign = {
+ let s = env.get_string(qrsign).expect("invalid key string").as_ptr();
+ let keylen = libc::strlen(s);
+ String::from_raw_parts(s as *mut u8, keylen, keylen)
+ };
+ let cardno = {
+ let s = env
+ .get_string(cardno)
+ .expect("invalid cardno string")
+ .as_ptr();
+ let len = libc::strlen(s);
+ String::from_raw_parts(s as *mut u8, len, len)
+ };
+
+ let termDatetime = {
+ let s = env
+ .get_string(termDatetime)
+ .expect("invalid datetime")
+ .as_ptr();
+ let len = libc::strlen(s);
+ String::from_raw_parts(s as *mut u8, len, len)
+ };
+
+ let result = env.get_map(result).expect("invalid qrdata map");
+
+ if termDatetime.len() != 14 {
+ put_data(&env, &result, "error", "term datetime must be 14 chars");
+ return JNI_FALSE;
+ }
+
+ match dlqrcode::transaction_tac(&cardno, amount, &termDatetime, &qrsign) {
+ Ok(tac) => {
+ put_data(&env, &result, "tac", &tac);
+ JNI_TRUE
+ }
+ Err(e) => {
+ put_data(&env, &result, "error", &format!("{:?}", e));
+ JNI_FALSE
+ }
+ }
+ }
}