use qrcode::QrCode;
use image::{Luma, Rgba, ImageBuffer, imageops, DynamicImage, ImageFormat};
use std::io::Cursor;
use base64::{engine::general_purpose, Engine};
use wasm_bindgen::{JsCast, JsValue};
use web_sys::{Response, js_sys::{Uint8Array, futures::JsFuture}};
use crate::services::crypto;
/// 이미지에 서명 정보를 담은 QR 코드를 오버랩핑하여 Data URL로 반환합니다.
pub async fn overlap_signature(
private_key: String,
message: String,
image_url: String
) -> String {
let signature = crypto::sign_message(&private_key, &message);
// 2. QR 코드 생성
let qr = generate_qr_data(&signature.as_bytes()).expect("QR 생성 실패");
let image_bytes = url_to_vec(&image_url).await.expect("object url 바이트 변환 실패");
// 3. 이미지 합성 및 결과 반환
apply_qr_stamp_bytes(image_bytes, &qr, 150, 20, 20, 0.8).expect("이미지 합성 실패")
}
fn generate_qr_data(data: &[u8]) -> Result<QrCode, Box<dyn std::error::Error>> {
let code = QrCode::new(data)?;
Ok(code)
}
fn apply_qr_stamp_bytes(image_bytes: Vec<u8>, qr_code: &QrCode, size: u32, x_pos: i64, y_pos: i64, opacity: f32) -> Result<String, Box<dyn std::error::Error>> {
// 1. 원본 이미지 로드
let mut img = image::load_from_memory(&image_bytes)?.to_rgba8();
let (image_w, image_h) = img.dimensions();
// 2. QR 코드를 이미지로 생성
let qr_luma = qr_code.render::<Luma<u8>>()
.max_dimensions(size, size)
.build();
let (qr_w, qr_h) = qr_luma.dimensions();
let alpha = (255.0 * opacity) as u8;
let qr_rgba = ImageBuffer::from_fn(qr_w, qr_h, |x, y| {
let luma_pixel = qr_luma.get_pixel(x, y);
if luma_pixel[0] < 128 {
Rgba([0, 0, 0, alpha])
} else {
Rgba([255, 255, 255, alpha])
}
});
let x_pos_lb = (image_w - qr_w) as i64 - x_pos;
let y_pos_lb = (image_h - qr_h) as i64 - y_pos;
// 3. 합성
imageops::overlay(&mut img, &qr_rgba, x_pos_lb, y_pos_lb);
// 4. 메모리 내에서 인코딩 후 Base64 반환
let mut buffer = Cursor::new(Vec::new());
DynamicImage::ImageRgba8(img).write_to(&mut buffer, ImageFormat::Png)?;
let base64_str = general_purpose::STANDARD.encode(buffer.into_inner());
Ok(format!("data:image/png;base64,{}", base64_str))
}
async fn url_to_vec(url: &str) -> Result<Vec<u8>, JsValue> {
// 1. URL로 fetch 요청
let window = web_sys::window().expect("window 없음");
let resp_value = JsFuture::from(window.fetch_with_str(url)).await?;
let resp: Response = resp_value.dyn_into()?;
// 2. 데이터를 ArrayBuffer로 변환
let buffer_value = JsFuture::from(resp.array_buffer()?).await?;
// 3. Uint8Array로 변환하여 Vec<u8>로 추출
let uint8_array = Uint8Array::new(&buffer_value);
Ok(uint8_array.to_vec())
}
예전에 내 사칭범들이 돌아다닐 때 서명에 쓰던 코드 일부
이걸로 사칭함 ㅅㄱ
내 개인키를 무슨 수로 알아내겠느뇨? - dc App
@글쓴 프갤러(221.149) 양자컴퓨터