一次有趣的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的将来是愈来愈有信心了。

相关文章
相关标签/搜索