最近在項目進程中趕上了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自帶的 sha512再加base64嘗試,結果計算結果與查詢到的字符串天差地別,一度陷入尷尬的境地。框架
既然在.Net Core中沒有現成的工具,因而就往C語言上靠一靠,因而乎,一個Linux下的密碼函數浮出水面:ide
char * crypt (const char *key,const char * salt);
使用此函數,直接能夠生成咱們所需的密碼。函數
做爲一個長期奮鬥在.Net環境中的程序員,想要調用Linux C函數庫中的函數,若是放在幾年前,那是想一想都感受本身是否是瘋了的感受,不過這.Net Core仍是給了咱們但願,在翻閱了了Githud上corefx庫(也就是.Net Core的框架源代碼)後,發現能夠經過DllImport來調用Linux的so動態連接庫。工具
因而,一個想法浮如今腦海中,使用C語言編譯so動態庫->使用.Net Core調用動態庫來實現咱們想要的功能。加密
這一塊,網上教程不少的,我就很少說了,貼上代碼: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文件。
這個就更不用說了,直接上代碼:
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.
經過此次的體驗,發現結合C語言.Net Core能夠在Linux下作幾乎全部事情,以前在瞭解到.Net Core 3.0只支持Windows窗口化編程的遺憾一掃而空,將GTK(好像Mono有個叫GTK#的東西,估計差很少原理)或者WxWeight一類的,用so形式從新封裝一下,感受開發窗口化程序也不會是什麼困難的事情(固然Linux下對窗口化的需求原本就比較低),反正無論怎麼樣,對.Net Core的將來是愈來愈有信心了。