Closed DSBloom closed 2 years ago
@nadcraker , does sample code https://github.com/Yubico/Yubico.NET.SDK/blob/831161f903e9e1ece60cefdf6627bdcc96a579c1/Yubico.YubiKey/examples/PivSampleCode/CertificateOperations/SampleCertificateOperations.cs help help? It has GetSelfSignedCert. To avoid any user prompts, you could use your own key collector delegate with PIN/PUK coming from the caller of your wrapper (you are probably already doing it for other commands).
This looks very promising. Thank you @gnida-rada!
@nadcraker , if you want it, I can share code for customizable promptless key collector (basically, you init it with pin, puk or both and then supply those values in delegate callback.
Yes please post it. I have my own key collector but I would love to see what you have. Maybe I can learn something from it.
using System; using Yubico.YubiKey;
public class YubikeyPivKeyCollector
{
private static readonly byte[] DefaultPin = { 0x31, 0x32, 0x33, 0x34, 0x35, 0x36 };
private static readonly byte[] DefaultMgmtKey = {
0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08,
0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08,
0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08 };
// or "0102030405060708" three times
public const string DefaultMgmtKeyString = "010203040506070801020304050607080102030405060708";
public const string DefaultPukString = "12345678";
private byte[] _pin;
private byte[] _newPin;
private byte[] _puk;
private byte[] _newPuk;
private byte[] _mgmtKey;
private byte[] _newMgmtKey;
private YubikeyPivKeyCollector(byte[] pin, byte[] mgmtKey)
{
_pin = pin;
_mgmtKey = mgmtKey;
}
public YubikeyPivKeyCollector()
{
}
private static readonly Lazy<YubikeyPivKeyCollector> lazyFactoryPresetKeyCollector =
new Lazy<YubikeyPivKeyCollector>(() => new YubikeyPivKeyCollector(
DefaultPin, DefaultMgmtKey));
public static YubikeyPivKeyCollector FactoryPresetKeyCollector
{
get
{
return lazyFactoryPresetKeyCollector.Value;
}
}
public void SetPinString(string pinString)
{
if (pinString == null)
{
throw new ArgumentNullException(nameof(pinString));
}
_pin = YubikeyPivUtils.ConvertPinStringToByteArray(pinString);
}
public void SetNewPinString(string newPinString)
{
if (newPinString == null)
{
throw new ArgumentNullException(nameof(newPinString));
}
_newPin = YubikeyPivUtils.ConvertPinStringToByteArray(newPinString);
}
public void SetPukString(string inString)
{
if (inString == null)
{
throw new ArgumentNullException(nameof(inString));
}
_puk = YubikeyPivUtils.ConvertPinStringToByteArray(inString);
}
public void SetNewPukString(string inString)
{
if (inString == null)
{
throw new ArgumentNullException(nameof(inString));
}
_newPuk = YubikeyPivUtils.ConvertPinStringToByteArray(inString);
}
public void SetMgmtKeyString(string mgmtKeyString)
{
if (mgmtKeyString == null)
{
throw new ArgumentNullException(nameof(mgmtKeyString));
}
_mgmtKey = YubikeyPivUtils.ConvertMgmtKeyStringToByteArray(mgmtKeyString);
}
public void SetNewMgmtKeyString(string mewMgmtKeyString)
{
if (mewMgmtKeyString == null)
{
throw new ArgumentNullException(nameof(mewMgmtKeyString));
}
_newMgmtKey = YubikeyPivUtils.ConvertMgmtKeyStringToByteArray(mewMgmtKeyString);
}
// This is the callback. When the SDK needs a PIN, PUK, or management
// key, this is the method that will be called.
public bool KeyCollectorDelegate(KeyEntryData keyEntryData)
{
if (keyEntryData is null)
{
return false;
}
if (keyEntryData.IsRetry == true)
{
// this is automatic key collector. If we don't know the values
// we are not promting the user for retry, just bail.
return false;
}
byte[] currentValue;
byte[] newValue = null;
switch (keyEntryData.Request)
{
default:
throw new NotImplementedException($"Unsupported keyEntryData.Request {keyEntryData.Request}!");
case KeyEntryRequest.Release:
return true;
case KeyEntryRequest.VerifyPivPin:
currentValue = _pin;
break;
case KeyEntryRequest.ChangePivPin:
if ((_pin == null) || (_newPin == null))
{
return false;
}
currentValue = _pin;
newValue = _newPin;
break;
case KeyEntryRequest.ChangePivPuk:
if ((_puk == null) || (_newPuk == null))
{
return false;
}
currentValue = _puk;
newValue = _newPuk;
break;
case KeyEntryRequest.AuthenticatePivManagementKey:
if (keyEntryData.IsRetry == true)
{
return false;
}
currentValue = _mgmtKey;
break;
case KeyEntryRequest.ChangePivManagementKey:
if (keyEntryData.IsRetry == true)
{
return false;
}
if ((_mgmtKey == null) || (_newMgmtKey == null))
{
return false;
}
currentValue = _mgmtKey;
newValue = _newMgmtKey;
break;
}
if (newValue is null)
{
keyEntryData.SubmitValue(currentValue);
}
else
{
keyEntryData.SubmitValues(currentValue, newValue);
}
return true;
}
}
Awesome, thanks! Where can I find the YubikeyPivUtils
class?
using System;
public static class YubikeyPivUtils
{
// for MgmtKeyString, we convert a hex string to a byte array.
// so "010203" becomes { 0x01, 0x02, 0x03 }
public static byte[] ConvertMgmtKeyStringToByteArray(string mgmtKeyString)
{
if (mgmtKeyString == null)
{
throw new ArgumentNullException(nameof(mgmtKeyString));
}
char[] valueChars = mgmtKeyString.ToCharArray();
byte[] keyArray = new byte[24];
int inIndex = 0;
int outIndex = 0;
while (inIndex < valueChars.Length)
{
byte firstDigit = (byte)Convert.ToInt32(valueChars[inIndex].ToString(), 16);
byte secondDigit = (byte)Convert.ToInt32(valueChars[inIndex + 1].ToString(), 16);
keyArray[outIndex] = (byte)((firstDigit * 16) + secondDigit);
inIndex += 2;
outIndex++;
if (outIndex >= 24)
{
break;
}
}
return keyArray;
}
// for PIN string, convert each character to its associated ASCII byte.
public static byte[] ConvertPinStringToByteArray(string pinString)
{
if (pinString == null)
{
throw new ArgumentNullException(nameof(pinString));
}
char[] valueChars = pinString.ToCharArray();
byte[] pinArray = new byte[valueChars.Length];
for (int index = 0; index < valueChars.Length; index++)
{
pinArray[index] = (byte)valueChars[index];
}
return pinArray;
}
}
With ykman we can do this
ykman.exe piv certificates generate
.We currently use ykman to generate a self signed cert for slot 9D.
I don't see a high level command to do the same with the SDK. Do we have to generate our own self signed cert and import using
ImportCertificate
fromPivSession
?