1. Linux
  2. 随笔一记

sudo-with-windows-hello

最近淘宝购入一台DIY Camera 支持 windows hello 如下

但是还没到,想起来曾经在ITHome上看到的一篇关于 WSL 支持windows hello 的新闻 https://www.ithome.com/0/541/285.htm

到Github看看, https://github.com/nullpo-head/WSL-Hello-sudo

 

无论如何,先按照README.md下载安装看看再说。

果然报错:

Error: Key creation failed due to some error

检查一下install.sh吧,这里截取问题点

echo "Please authenticate yourself now to create a credential for '$USER' and '$WINUSER' pair."
KEY_ALREADY_EXIST_ERR=170
set -x
pushd $PAM_WSL_HELLO_WINPATH
WindowsHelloKeyCredentialCreator/WindowsHelloKeyCredentialCreator.exe pam_wsl_hello_$USER|| test $? = $KEY_ALREADY_EXIST_ERR
sudo mkdir -p /etc/pam_wsl_hello/public_keys
popd
sudo cp "$PAM_WSL_HELLO_WINPATH"/pam_wsl_hello_$USER.pem /etc/pam_wsl_hello/public_keys/

在执行WindowsHelloKeyCredentialCreator.exe 出现的问题。好家伙,这个小日本用的是c#写的这个,那就把他源码下载下来看看吧。

源码下载下来使用我的 visual studio2017打开WindowsHelloKeyCredentialCreator.sln这个项目,

using System;
using System.IO;
using System.Threading.Tasks;
using Windows.Security.Credentials;
using Windows.Security.Cryptography;
using Windows.Storage.Streams;

namespace WindowsHelloKeyCredentialCreator
{
    class Program
    {

        public const int ERR_CREAT_FAIL = 1;
        public const int ERR_CREAT_KEY_EXISTS = 170; // Avoid reserved exit codes of UNIX

        static async Task<(int err, string pubKey)> CreatePublicKey(string key_name)
        {
            int err;
            var createRes = await KeyCredentialManager.RequestCreateAsync(key_name, KeyCredentialCreationOption.FailIfExists);
            IBuffer pubKey;
            if (createRes.Status == KeyCredentialStatus.CredentialAlreadyExists)
            {
                var existing = await KeyCredentialManager.OpenAsync(key_name);
                if (existing.Status != KeyCredentialStatus.Success)
                {
                    return (ERR_CREAT_FAIL, null);
                }
                err = ERR_CREAT_KEY_EXISTS;
                pubKey = existing.Credential.RetrievePublicKey();
            }
            else if (createRes.Status != KeyCredentialStatus.Success)
            {
                return (ERR_CREAT_FAIL, null);
            }
            else {
                err = 0;
                pubKey = createRes.Credential.RetrievePublicKey();
            }
            var pem = String.Format("-----BEGIN PUBLIC KEY-----\n{0}\n-----END PUBLIC KEY-----\n", CryptographicBuffer.EncodeToBase64String(pubKey));
            return (err, pem);
        }

        static void exit(int code, bool needPrompt)
        {
            if (needPrompt)
            {
                Console.WriteLine("Hit Enter key to terminate...");
                Console.ReadLine();
            }
            Environment.Exit(code);
        }

        static void Main(string[] args)
        {
            string key_name;
            foreach (var arg in args)
            {
                if (arg == "-h" || arg == "/?")
                {
                    Console.WriteLine("Usage: WindowsHelloKeyCredentialCreator.exe [key_name]");
                    Console.WriteLine("This program creates a KeyCredential of Windows Hello, and save it to a file named 'key_name.pem'.");
                    Console.WriteLine("If key_name is not given, the prompt to ask the name will be shown.");
                    return;
                }
            }

            bool needsPrompt = args.Length == 0;

            if (needsPrompt)
            {
                Console.WriteLine("Input the name of the new KeyCredential");
                Console.Write("Name: ");
                key_name = Console.ReadLine();
            }
            else
            {
                key_name = args[0];
            }

            var res = CreatePublicKey(key_name).Result;
            if (res.err == ERR_CREAT_KEY_EXISTS)
            {
                Console.WriteLine("Error: The key already exists. Outputting The existing public key.");
            }
            else if (res.err > 0) {
                Console.WriteLine("Error: Key creation failed due to some error");
                exit(res.err, needsPrompt);
            }

            File.WriteAllText(String.Format("{0}.pem", key_name), res.pubKey);
            Console.WriteLine(String.Format("Done. The public credential key is written in '{0}.pem'", key_name));
            exit(res.err, needsPrompt);
        }
    }
}

代码很少,就这一点点,出错的就是这一句:

var createRes = await KeyCredentialManager.RequestCreateAsync(key_name, KeyCredentialCreationOption.FailIfExists);

返回的是NULL,也没看到报啥错,服了

翻一下doc看看

https://docs.microsoft.com/zh-hk/uwp/api/windows.security.credentials.keycredentialmanager.requestcreateasync?view=winrt-20348

没用的doc

最后通过stackoverflow 找到了这个

https://docs.microsoft.com/en-us/windows/uwp/security/microsoft-passport

好家伙,这大概就是这个项目的原理了

随便看看,发现了这个例子:

var keyCredentialAvailable = await KeyCredentialManager.IsSupportedAsync();
if (!keyCredentialAvailable)
{
    // User didn't set up PIN yet
    return;
}

难道是我的设备没开PIN或是不支持?(不会吧?)

把验证加进去试试吧?

好家伙,打开设置看看!

靠,果然没有添加,添加一个吧!

然后再去执行一下install.sh

OK.安装成功!

测试一下

NICE.