commit 6d474abac02929a7ea25ecbabb21c4b5c31f9989
Author: taynpg <taynpg@163.com>
Date:   Mon Dec 30 15:12:03 2024 +0800

    first commit

diff --git a/.clang-format b/.clang-format
new file mode 100644
index 0000000..402f22e
--- /dev/null
+++ b/.clang-format
@@ -0,0 +1,17 @@
+BasedOnStyle: LLVM
+IndentWidth: 4
+PointerAlignment: Left
+AccessModifierOffset: -4
+BreakBeforeBraces: Custom
+BraceWrapping:
+    AfterFunction: true
+    AfterClass: true
+Cpp11BracedListStyle: true
+ReflowComments: true
+SpacesBeforeTrailingComments: 3
+TabWidth: 4
+ConstructorInitializerAllOnOneLineOrOnePerLine: true
+ColumnLimit: 80
+AllowShortBlocksOnASingleLine: Never
+AllowShortFunctionsOnASingleLine: None
+AllowShortEnumsOnASingleLine: false
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..5b861d3
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,4 @@
+build
+.vs
+.cache
+cmake-*
\ No newline at end of file
diff --git a/.vscode/settings.json b/.vscode/settings.json
new file mode 100644
index 0000000..7f62b22
--- /dev/null
+++ b/.vscode/settings.json
@@ -0,0 +1,89 @@
+{
+    "files.autoSave": "onFocusChange",
+    "editor.fontSize": 15,
+    "editor.fontFamily": "'Source Code Pro', 'Courier New', monospace",
+    "terminal.integrated.fontFamily": "Source Code Pro",
+    "cmake.configureOnOpen": true,
+    "cmake.debugConfig": {
+        "console": "integratedTerminal",
+        "setupCommands": [
+            {
+                "description": "-gdb-set charset utf-8",
+                "text": "-gdb-set charset UTF-8"
+            },
+            {
+                "description": "Enable gdb pretty-printing",
+                "text": "-enable-pretty-printing",
+                "ignoreFailures": true
+            }
+        ],
+        "args": [
+        ]
+    },
+    "cmake.configureSettings": {
+	    "CMAKE_TOOLCHAIN_FILE": "${env:VCPKG_ROOT}/scripts/buildsystems/vcpkg.cmake"
+    },
+    "cmake.options.statusBarVisibility": "visible",
+    "cmake.generator": "Ninja",
+    "C_Cpp.default.compileCommands": "${workspaceRoot}/build/compile_commands.json",
+    "C_Cpp.default.cppStandard": "c++17",
+    "editor.inlayHints.enabled": "off",
+    "editor.unicodeHighlight.allowedLocales": {
+        "ja": true,
+        "zh-hant": true,
+        "zh-hans": true
+    },
+    "files.associations": {
+        "atomic": "cpp",
+        "cctype": "cpp",
+        "charconv": "cpp",
+        "clocale": "cpp",
+        "cmath": "cpp",
+        "cstddef": "cpp",
+        "cstdint": "cpp",
+        "cstdio": "cpp",
+        "cstdlib": "cpp",
+        "cstring": "cpp",
+        "ctime": "cpp",
+        "cwchar": "cpp",
+        "exception": "cpp",
+        "initializer_list": "cpp",
+        "ios": "cpp",
+        "iosfwd": "cpp",
+        "iostream": "cpp",
+        "istream": "cpp",
+        "iterator": "cpp",
+        "limits": "cpp",
+        "locale": "cpp",
+        "memory": "cpp",
+        "new": "cpp",
+        "ostream": "cpp",
+        "stdexcept": "cpp",
+        "streambuf": "cpp",
+        "string": "cpp",
+        "system_error": "cpp",
+        "tuple": "cpp",
+        "type_traits": "cpp",
+        "typeinfo": "cpp",
+        "utility": "cpp",
+        "xfacet": "cpp",
+        "xiosbase": "cpp",
+        "xlocale": "cpp",
+        "xlocbuf": "cpp",
+        "xlocinfo": "cpp",
+        "xlocmes": "cpp",
+        "xlocmon": "cpp",
+        "xlocnum": "cpp",
+        "xloctime": "cpp",
+        "xmemory": "cpp",
+        "xmemory0": "cpp",
+        "xstddef": "cpp",
+        "xstring": "cpp",
+        "xtr1common": "cpp",
+        "xutility": "cpp",
+        "bit": "cpp",
+        "compare": "cpp",
+        "concepts": "cpp",
+        "format": "cpp"
+    }
+}
\ No newline at end of file
diff --git a/CMakeLists.txt b/CMakeLists.txt
new file mode 100644
index 0000000..99ac8ce
--- /dev/null
+++ b/CMakeLists.txt
@@ -0,0 +1,23 @@
+cmake_minimum_required(VERSION 3.16)
+
+project(md5_sha256 LANGUAGES CXX)
+set(CMAKE_CXX_STANDARD 17)
+set(CMAKE_CXX_STANDARD_REQUIRED ON)
+
+if (MSVC)
+    add_compile_options(/source-charset:utf-8)
+endif()
+
+message(STATUS "System: ${CMAKE_SYSTEM_NAME}")
+message(STATUS "Compiler CXX ID: ${CMAKE_CXX_COMPILER_ID}")
+
+set(LIBRARY_OUTPUT_PATH ${PROJECT_BINARY_DIR}/lib/${CMAKE_BUILD_TYPE})
+set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${PROJECT_BINARY_DIR}/bin/${CMAKE_BUILD_TYPE}/)
+
+find_package(OpenSSL REQUIRED)
+add_executable(sha256 sha256.cpp)
+target_link_libraries(sha256 PRIVATE OpenSSL::SSL)
+target_link_libraries(sha256 PRIVATE OpenSSL::Crypto)
+add_executable(md5 md5.cpp)
+target_link_libraries(md5 PRIVATE OpenSSL::SSL)
+target_link_libraries(md5 PRIVATE OpenSSL::Crypto)
\ No newline at end of file
diff --git a/README.md b/README.md
new file mode 100644
index 0000000..a0ab985
--- /dev/null
+++ b/README.md
@@ -0,0 +1,5 @@
+## md5_sha256
+
+md5_sha256命令行工具。
+
+`vcpkg install openssl`。
\ No newline at end of file
diff --git a/md5.cpp b/md5.cpp
new file mode 100644
index 0000000..519ba99
--- /dev/null
+++ b/md5.cpp
@@ -0,0 +1,70 @@
+#include <openssl/md5.h>
+#include <fstream>
+#include <iostream>
+#include <iomanip>
+#include <sstream>
+#include <vector>
+
+std::string to_hex_string(const unsigned char* hash, size_t length) {
+    std::ostringstream oss;
+    for (size_t i = 0; i < length; ++i) {
+        oss << std::hex << std::setw(2) << std::setfill('0') << static_cast<int>(hash[i]);
+    }
+    return oss.str();
+}
+
+std::string md5_string(const std::string& input) {
+    unsigned char hash[MD5_DIGEST_LENGTH];
+    MD5(reinterpret_cast<const unsigned char*>(input.c_str()), input.size(), hash);
+    return to_hex_string(hash, MD5_DIGEST_LENGTH);
+}
+
+std::string md5_file(const std::string& filename) {
+    std::ifstream file(filename, std::ios::binary);
+    if (!file) {
+        throw std::runtime_error("Cannot open file: " + filename);
+    }
+
+    MD5_CTX ctx;
+    MD5_Init(&ctx);
+
+    std::vector<char> buffer(8192);
+    while (file.good()) {
+        file.read(buffer.data(), buffer.size());
+        MD5_Update(&ctx, buffer.data(), file.gcount());
+    }
+
+    unsigned char hash[MD5_DIGEST_LENGTH];
+    MD5_Final(hash, &ctx);
+
+    return to_hex_string(hash, MD5_DIGEST_LENGTH);
+}
+
+int main(int argc, char* argv[]) {
+    if (argc != 3) {
+        std::cerr << "Usage: " << argv[0] << " <mode> <input>" << std::endl;
+        std::cerr << "Modes:" << std::endl;
+        std::cerr << "  -s : Calculate MD5 for a string" << std::endl;
+        std::cerr << "  -f : Calculate MD5 for a file" << std::endl;
+        return 1;
+    }
+
+    std::string mode = argv[1];
+    std::string input = argv[2];
+
+    try {
+        if (mode == "-s") {
+            std::cout << "MD5(string): " << md5_string(input) << std::endl;
+        } else if (mode == "-f") {
+            std::cout << "MD5(file): " << md5_file(input) << std::endl;
+        } else {
+            std::cerr << "Invalid mode: " << mode << std::endl;
+            return 1;
+        }
+    } catch (const std::exception& e) {
+        std::cerr << "Error: " << e.what() << std::endl;
+        return 1;
+    }
+
+    return 0;
+}
diff --git a/sha256.cpp b/sha256.cpp
new file mode 100644
index 0000000..9425958
--- /dev/null
+++ b/sha256.cpp
@@ -0,0 +1,70 @@
+#include <openssl/sha.h>
+#include <fstream>
+#include <iostream>
+#include <iomanip>
+#include <sstream>
+#include <vector>
+
+std::string to_hex_string(const unsigned char* hash, size_t length) {
+    std::ostringstream oss;
+    for (size_t i = 0; i < length; ++i) {
+        oss << std::hex << std::setw(2) << std::setfill('0') << static_cast<int>(hash[i]);
+    }
+    return oss.str();
+}
+
+std::string sha256_string(const std::string& input) {
+    unsigned char hash[SHA256_DIGEST_LENGTH];
+    SHA256(reinterpret_cast<const unsigned char*>(input.c_str()), input.size(), hash);
+    return to_hex_string(hash, SHA256_DIGEST_LENGTH);
+}
+
+std::string sha256_file(const std::string& filename) {
+    std::ifstream file(filename, std::ios::binary);
+    if (!file) {
+        throw std::runtime_error("Cannot open file: " + filename);
+    }
+
+    SHA256_CTX ctx;
+    SHA256_Init(&ctx);
+
+    std::vector<char> buffer(8192);
+    while (file.good()) {
+        file.read(buffer.data(), buffer.size());
+        SHA256_Update(&ctx, buffer.data(), file.gcount());
+    }
+
+    unsigned char hash[SHA256_DIGEST_LENGTH];
+    SHA256_Final(hash, &ctx);
+
+    return to_hex_string(hash, SHA256_DIGEST_LENGTH);
+}
+
+int main(int argc, char* argv[]) {
+    if (argc != 3) {
+        std::cerr << "Usage: " << argv[0] << " <mode> <input>" << std::endl;
+        std::cerr << "Modes:" << std::endl;
+        std::cerr << "  -s : Calculate SHA-256 for a string" << std::endl;
+        std::cerr << "  -f : Calculate SHA-256 for a file" << std::endl;
+        return 1;
+    }
+
+    std::string mode = argv[1];
+    std::string input = argv[2];
+
+    try {
+        if (mode == "-s") {
+            std::cout << "SHA-256(string): " << sha256_string(input) << std::endl;
+        } else if (mode == "-f") {
+            std::cout << "SHA-256(file): " << sha256_file(input) << std::endl;
+        } else {
+            std::cerr << "Invalid mode: " << mode << std::endl;
+            return 1;
+        }
+    } catch (const std::exception& e) {
+        std::cerr << "Error: " << e.what() << std::endl;
+        return 1;
+    }
+
+    return 0;
+}