2022年10月10日 星期一

MD5 筆記

MD5 Intro

MD5 訊息摘要演算法(英語:MD5 Message-Digest Algorithm),一種被廣泛使用的密碼雜湊函式,可以產生出一個128位元(16個字元(BYTES))的雜湊值(hash value),用於確保資訊傳輸完整一致。(節自wiki)

簡易 MD5 工具 : md5sum

基本上 Unix, Linux 的作業系統都有預設 md5sum
  • md5sum 用法
        # pipe
        $ echo "123" | md5sum
        ba1f2511fc30423bdbb183fe33f3dd0f  -
    
        # 讀檔
        $ md5sum .gitignore
        247bc32fd24d78844194917cb32d556a  .gitignore
    
        # check
        $ md5sum .gitignore > tmp.md5
        $ md5sum -c tmp.md5
        .gitignore: OK
    
        # pipe check
        $ echo "247bc32fd24d78844194917cb32d556a .gitignore" | md5sum -c
        .gitignore: OK
    

openssl/evp.h

The EVP digest routines are a high level interface to message digests (節自 Linux man page)。這裡註記一下 EVP 大概是代表 Envelope。雖然現在已經被改掉,但以前的 openssl/evp.h 的 #ifndef 是 HEADER_ENVELOPE_H。
  • evp 大概的流程
        #include <stdio.h>
        #include <string.h>
        #include <openssl/evp.h>
    
        int main(int argc, char *argv[])
        {
            EVP_MD_CTX *mdctx;
            const EVP_MD *md;
            char mess1[] = "Test Message\n";
            char mess2[] = "Hello World\n";
            unsigned char md_value[EVP_MAX_MD_SIZE];
            unsigned int md_len, i;
    
            if (argv[1] == NULL) {
                printf("Usage: mdtest digestname\n");
                exit(1);
            }
    
            OpenSSL_add_all_algorithms(); // 有可能有些 algo 沒有 load, ex. RSA-SHA1
            md = EVP_get_digestbyname(argv[1]);
            if (md == NULL) {
                printf("Unknown message digest %s\n", argv[1]);
                exit(1);
            }
    
            mdctx = EVP_MD_CTX_new();
            EVP_DigestInit_ex(mdctx, md, NULL); // _ex() 較有效率, 以前的 code 可能是 EVP_DigestInit()
            EVP_DigestUpdate(mdctx, mess1, strlen(mess1));
            EVP_DigestUpdate(mdctx, mess2, strlen(mess2));
            EVP_DigestFinal_ex(mdctx, md_value, &md_len);
            EVP_MD_CTX_free(mdctx);
    
            printf("Digest is: ");
            for (i = 0; i < md_len; i++)
                printf("%02x", md_value[i]);
            printf("\n");
    
            exit(0);
        }
    
參考資料 :
1.MD5 wiki
2.MD5SUM wiki
3.linux man page
4.stackoverflow

2022年10月9日 星期日

讀取 Linux file info (stat)

讀取 Linux 的檔案資訊

Linux 的檔案有很多資訊,即使只用到檔案大小也是很方便。

stat

  • struct stat
    stat 的資料結構
        #include <sys/stat.h>
    
        struct stat {
            dev_t     st_dev;         /* ID of device containing file */
            ino_t     st_ino;         /* Inode number */
            mode_t    st_mode;        /* File type and mode */
            nlink_t   st_nlink;       /* Number of hard links */
            uid_t     st_uid;         /* User ID of owner */
            gid_t     st_gid;         /* Group ID of owner */
            dev_t     st_rdev;        /* Device ID (if special file) */
            off_t     st_size;        /* Total size, in bytes */
            blksize_t st_blksize;     /* Block size for filesystem I/O */
            blkcnt_t  st_blocks;      /* Number of 512B blocks allocated */
    
            /* Since Linux 2.6, the kernel supports nanosecond
                precision for the following timestamp fields.
                For the details before Linux 2.6, see NOTES. */
    
            struct timespec st_atim;  /* Time of last access */
            struct timespec st_mtim;  /* Time of last modification */
            struct timespec st_ctim;  /* Time of last status change */
    
            #define st_atime st_atim.tv_sec      /* Backward compatibility */
            #define st_mtime st_mtim.tv_sec
            #define st_ctime st_ctim.tv_sec
        };
    
  • struct stat
    讀取檔案 (這裡讀 .gitignore)
        #include <stdio.h>    // for printf
        #include <time.h>     // for ctime
        #include <sys/stat.h>
    
        int main()
        {
            struct stat st;
            // 0 success, -1 failed
            // error code: errno
            if(stat(".gitignore", &st) == -1){
                return -1;
            }
            printf("I-node number:             %ld\n", (long) st.st_ino);
            printf("Mode:                      %lo (octal)\n", (unsigned long) st.st_mode);
            printf("Link count:                %ld\n", (long) st.st_nlink);
            printf("Ownership:                 UID=%ld   GID=%ld\n", (long) st.st_uid, (long) st.st_gid);
            printf("device containing file id: %ld\n", (long) st.st_dev);
            printf("device id:                 %ld\n", (long) st.st_rdev);
            printf("File size:                 %lld bytes\n", (long long) st.st_size);
            printf("Preferred I/O block size:  %ld bytes\n", (long) st.st_blksize);
            printf("Blocks allocated:          %lld\n", (long long) st.st_blocks);
            printf("Last status change:        %s", ctime(&st.st_ctime));
            printf("Last file access:          %s", ctime(&st.st_atime));
            printf("Last file modification:    %s", ctime(&st.st_mtime));
            return 0;
        }
    
        I-node number:             20057552
        Mode:                      100664 (octal)
        Link count:                1
        Ownership:                 UID=1000   GID=1000
        device containing file id: 66306
        device id:                 0
        File size:                 16 bytes
        Preferred I/O block size:  4096 bytes
        Blocks allocated:          8
        Last status change:        Tue Mar 29 14:03:01 2022
        Last file access:          Sun Oct  9 19:02:52 2022
        Last file modification:    Thu Jun 17 10:20:57 2021
    
參考資料 :
1.Linux manual page
2.程式人生

Popular Posts