一次有趣的Linux下.Net Core與C語言的合做開發體驗:生成Linux標準的用戶密碼串

最近在項目進程中趕上了Linux用戶驗證的問題,想着怎麼樣經過Linux本地用戶進行安全校驗,因而去查了些資料。程序員

Linux的密碼存儲

查閱資料後發現早期的Linux存儲在/etc/password文件中,由於/etc/password權限控制較弱,如今已經不使用了,因此咱們這裏就不討論這個文件了,較新的Linux發行版,密碼都是存儲在/etc/shadow文件中,由於/etc/shadow是管理員權限訪問,安全性高出許多,咱們可使用命令來查看文件:編程

$ sudo cat /etc/shadow

以我真實的用戶信息(用戶名 inmount 密碼 123456)爲例:安全

......
inmount:$6$GTAgpXtw/YsqmaOJ$19/NZg8CVbQJB2BZBRFePGJj8f9Zme0s/VjmjdRjxJ9ItePem3h20tyGOk5Ytu5yIWio.0X.kwcsocfgIm2HY.:18211:0:99999:7:::
......

其中的$6$GTAgpXtw/YsqmaOJ$19/NZg8CVbQJB2BZBRFePGJj8f9Zme0s/VjmjdRjxJ9ItePem3h20tyGOk5Ytu5yIWio.0X.kwcsocfgIm2HY.就是用戶密碼加密後的字符串,$6表明爲基於sha512加密運算,$GTAgpXtw/YsqmaOJ則是一串隨機密鑰。bash

使用 .Net Core 的進行簡單嘗試

針對字符串的簡單觀察後,採用.net core自帶的 sha512再加base64嘗試,結果計算結果與查詢到的字符串天差地別,一度陷入尷尬的境地。框架

C語言中的密碼函數

既然在.Net Core中沒有現成的工具,因而就往C語言上靠一靠,因而乎,一個Linux下的密碼函數浮出水面:ide

char * crypt (const char *key,const char * salt);

使用此函數,直接能夠生成咱們所需的密碼。函數

探索Linux的動態連接庫

做爲一個長期奮鬥在.Net環境中的程序員,想要調用Linux C函數庫中的函數,若是放在幾年前,那是想一想都感受本身是否是瘋了的感受,不過這.Net Core仍是給了咱們但願,在翻閱了了Githud上corefx庫(也就是.Net Core的框架源代碼)後,發現能夠經過DllImport來調用Linux的so動態連接庫。工具

因而,一個想法浮如今腦海中,使用C語言編譯so動態庫->使用.Net Core調用動態庫來實現咱們想要的功能。加密

製做so動態連接庫

這一塊,網上教程不少的,我就很少說了,貼上代碼:spa

library.h

#ifndef CRYPT_LIBRARY_H
#define CRYPT_LIBRARY_H

char *getpassword(const char *key, const char *slat);

#endif //CRYPT_LIBRARY_H

library.c

#include "library.h"
#include <crypt.h>

char *getpassword(const char *key, const char *slat) {
    return crypt(key, slat);
}

編譯so庫:

gcc library.c -fPIC -shared -o libcrypt.so -lcrypt

獲得了一個Linux下的標準動態鏈接庫libcrypt.so文件。

使用.Net Core調用so文件

這個就更不用說了,直接上代碼:

using System;
using System.Runtime.InteropServices;

namespace App {

    class Program {

        [DllImport("libcrypt.so",
            EntryPoint = "getpassword",
            CallingConvention = CallingConvention.Cdecl,
            CharSet = CharSet.Ansi,
            SetLastError = true)]
        public static extern IntPtr getpassword(IntPtr key, IntPtr slat);

        [DllImport("libcrypt.so",
            EntryPoint = "getpassword",
            CallingConvention = CallingConvention.Cdecl,
            CharSet = CharSet.Ansi,
            SetLastError = true)]
        public static extern string getpassword(string key, string slat);

        static void Main(string[] args) {
            Console.WriteLine(getpassword("123456", "$6$GTAgpXtw/YsqmaOJ"));
            Console.WriteLine(Marshal.PtrToStringAnsi(getpassword(Marshal.StringToHGlobalAnsi("123456"), Marshal.StringToHGlobalAnsi("$6$GTAgpXtw/YsqmaOJ"))));
        }
    }
}

代碼中根據原函數定義中的字符指針的特色,可使用字符串或者指針類型兩種處理方式,其結果是同樣的,下面是運行結果(須要將libcrypt.so文件拷貝到執行目錄下,並在Linux環境下運行,在Windows環境下運行會提示錯誤):

$6$GTAgpXtw/YsqmaOJ$19/NZg8CVbQJB2BZBRFePGJj8f9Zme0s/VjmjdRjxJ9ItePem3h20tyGOk5Ytu5yIWio.0X.kwcsocfgIm2HY.
$6$GTAgpXtw/YsqmaOJ$19/NZg8CVbQJB2BZBRFePGJj8f9Zme0s/VjmjdRjxJ9ItePem3h20tyGOk5Ytu5yIWio.0X.kwcsocfgIm2HY.

吹一波.Net Core

經過此次的體驗,發現結合C語言.Net Core能夠在Linux下作幾乎全部事情,以前在瞭解到.Net Core 3.0只支持Windows窗口化編程的遺憾一掃而空,將GTK(好像Mono有個叫GTK#的東西,估計差很少原理)或者WxWeight一類的,用so形式從新封裝一下,感受開發窗口化程序也不會是什麼困難的事情(固然Linux下對窗口化的需求原本就比較低),反正無論怎麼樣,對.Net Core的將來是愈來愈有信心了。

相關文章
相關標籤/搜索