From 422062226dc2c0b1f84b8fa07a483a645227d8e6 Mon Sep 17 00:00:00 2001 From: Vladimir Dostoyevskiy <99822064+VDostoyevskiy@users.noreply.github.com> Date: Sun, 25 Feb 2024 14:07:32 +0800 Subject: [PATCH] Move to rust sha1 impl (#782) * Move to rust sha1 impl * Use onstack buffer Signed-off-by: GG Bond --------- Signed-off-by: GG Bond Co-authored-by: GG Bond --- app/src/main/cpp/CMakeLists.txt | 2 +- app/src/main/cpp/hash.c | 39 --------------------------------- app/src/main/rust/Cargo.toml | 2 ++ app/src/main/rust/src/lib.rs | 38 +++++++++++++++++++++++++++++--- 4 files changed, 38 insertions(+), 43 deletions(-) delete mode 100644 app/src/main/cpp/hash.c diff --git a/app/src/main/cpp/CMakeLists.txt b/app/src/main/cpp/CMakeLists.txt index 0c7d4fda2..c0acd7cbf 100644 --- a/app/src/main/cpp/CMakeLists.txt +++ b/app/src/main/cpp/CMakeLists.txt @@ -85,5 +85,5 @@ FetchContent_MakeAvailable(Corrosion) corrosion_import_crate(MANIFEST_PATH ../rust/Cargo.toml) # Build and link our app's native lib -add_library(${PROJECT_NAME} SHARED archive.c border.c gifutils.c hash.c natsort/strnatcmp.c) +add_library(${PROJECT_NAME} SHARED archive.c border.c gifutils.c natsort/strnatcmp.c) target_link_libraries(${PROJECT_NAME} ehviewer_rust archive_static log jnigraphics) diff --git a/app/src/main/cpp/hash.c b/app/src/main/cpp/hash.c deleted file mode 100644 index 1a199b934..000000000 --- a/app/src/main/cpp/hash.c +++ /dev/null @@ -1,39 +0,0 @@ -#include - -#include -#include - -#include "ehviewer.h" - -#define BUFFER_SIZE 8192 - -typedef uint8_t byte; - -const char hex_digits[] = "0123456789abcdef"; - -JNIEXPORT jstring JNICALL -Java_com_hippo_ehviewer_jni_HashKt_sha1(JNIEnv *env, jclass clazz, jint fd) { - EH_UNUSED(clazz); - struct sha1_ctx ctx; - sha1_init(&ctx); - - size_t bytes_read; - byte buffer[BUFFER_SIZE]; - while ((bytes_read = read(fd, buffer, BUFFER_SIZE)) > 0) { - sha1_update(&ctx, bytes_read, buffer); - } - - byte digest[SHA1_DIGEST_SIZE]; - sha1_digest(&ctx, SHA1_DIGEST_SIZE, digest); - - byte byte; - char hex_digest[2 * SHA1_DIGEST_SIZE + 1]; - for (int i = 0; i < SHA1_DIGEST_SIZE; i++) { - byte = digest[i]; - hex_digest[2 * i] = hex_digits[byte >> 4 & 0xF]; - hex_digest[2 * i + 1] = hex_digits[byte & 0xF]; - } - hex_digest[2 * SHA1_DIGEST_SIZE] = '\0'; - - return (*env)->NewStringUTF(env, hex_digest); -} diff --git a/app/src/main/rust/Cargo.toml b/app/src/main/rust/Cargo.toml index f45f80063..bc49910cf 100644 --- a/app/src/main/rust/Cargo.toml +++ b/app/src/main/rust/Cargo.toml @@ -17,6 +17,8 @@ android_logger = { default-features = false, version = "0.13" } once_cell = { default-features = false, version = "1.19" } serde_cbor = "0.11" serde = { version = "1.0", features = ["derive"] } +sha1 = { version = "0.10" } +base16ct = { version = "0.2" } [profile.release] panic = "abort" diff --git a/app/src/main/rust/src/lib.rs b/app/src/main/rust/src/lib.rs index 95ee47dfc..0a7ca361d 100644 --- a/app/src/main/rust/src/lib.rs +++ b/app/src/main/rust/src/lib.rs @@ -1,6 +1,7 @@ mod parser; extern crate android_logger; +extern crate base16ct; extern crate jni; extern crate jni_fn; extern crate log; @@ -8,16 +9,22 @@ extern crate once_cell; extern crate quick_xml; extern crate regex_lite; extern crate serde; +extern crate sha1; extern crate tl; use android_logger::Config; -use jni::objects::JByteBuffer; -use jni::sys::{jint, JavaVM, JNI_VERSION_1_6}; +use base16ct::lower::encode_str; +use jni::objects::{JByteBuffer, JClass}; +use jni::sys::{jint, jstring, JavaVM, JNI_VERSION_1_6}; use jni::JNIEnv; +use jni_fn::jni_fn; use log::LevelFilter; use serde::Serialize; +use sha1::{Digest, Sha1}; use std::ffi::c_void; -use std::io::Cursor; +use std::fs::File; +use std::io::{copy, Cursor}; +use std::os::fd::BorrowedFd; use std::ptr::slice_from_raw_parts_mut; use std::str::from_utf8_unchecked; use tl::{Bytes, Node, NodeHandle, Parser, VDom}; @@ -122,3 +129,28 @@ pub extern "system" fn JNI_OnLoad(_: JavaVM, _: *mut c_void) -> jint { android_logger::init_once(Config::default().with_max_level(LevelFilter::Debug)); JNI_VERSION_1_6 } + +#[no_mangle] +#[allow(non_snake_case)] +#[jni_fn("com.hippo.ehviewer.jni.HashKt")] +pub fn sha1(mut env: JNIEnv, _class: JClass, fd: jint) -> jstring { + let mut sha = Sha1::new(); + let borrowed_fd = unsafe { BorrowedFd::borrow_raw(fd) }; + let owned_fd = match borrowed_fd.try_clone_to_owned() { + Ok(fd) => fd, + Err(err) => return throw_msg(&mut env, &format!("{err}")) as jstring, + }; + if let Err(err) = copy(&mut File::from(owned_fd), &mut sha) { + return throw_msg(&mut env, &format!("{err}")) as jstring; + }; + let digest = sha.finalize(); + let mut hex_digest = [0u8; 40]; + let hex = match encode_str(&digest, &mut hex_digest) { + Ok(str) => str, + Err(err) => return throw_msg(&mut env, &format!("{err}")) as jstring, + }; + match env.new_string(hex) { + Ok(obj) => obj.into_raw(), + Err(err) => throw_msg(&mut env, &format!("{err}")) as jstring, + } +}