-
Notifications
You must be signed in to change notification settings - Fork 5
/
X509ToOpenSSH.psm1
91 lines (77 loc) · 3.77 KB
/
X509ToOpenSSH.psm1
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
Function ConvertHex-ToBase64 {
<#
.DESCRIPTION
Helper function for converting binary written has hexadecimal to base64
.PARAMETER HexString
Expected format is a string of hexadecimal characters with no spaces or separation between the octets.
#>
[CmdletBinding()]
Param (
[Parameter(Mandatory = $true, Position = 1)]
[string]$HexString
)
$ByteArray = [System.Byte[]]::new($HexString.Length / 2)
For ($i = 0; $i -lt $ByteArray.Length; $i++) {
$ByteArray[$i] = [System.Convert]::ToByte($HexString.Substring($i * 2, 2), 16)
}
Write-Output ([System.Convert]::ToBase64String($ByteArray))
}
Function ConvertX509Cert2-ToOpenSshPubKey {
<#
.SYNOPSIS
Convert a X509Certificate2 object to OpenSSH public key format.
.DESCRIPTION
Accepts a X509Certificate2 object and utilizes the public key to output it in OpenSSH format for use in SSH public key authentication.
.PARAMETER Certificate
A single X509Certificate2 object from .NET.
.EXAMPLE
$Cert = Get-ChildItem Cert:\CurrentUser\My\A4321234CAF8EFACF74A8567D61F04ACA4321234
ConvertX509Cert2-ToOpenSshPubKey -Certificate $Cert
ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDCurn...ccwdiJ1 CAPI:A4321234CAF8EFACF74A8567D61F04ACA4321234 CN=SMITH.BOB.JONES, OU=PKI, OU=Office, O=Company, C=US
#>
[CmdletBinding()]
Param (
[Parameter(Mandatory = $false, Position = 1)]
[System.Security.Cryptography.X509Certificates.X509Certificate2]$Certificate
)
If ($null -eq $Certificate -or '' -eq $Certificate) {
Add-Type -AssemblyName System.Security
$ValidCerts = [System.Security.Cryptography.X509Certificates.X509Certificate2[]](Get-ChildItem 'Cert:\CurrentUser\My' | Where-object {$PSItem.Extensions.EnhancedKeyUsages.Value -eq '1.3.6.1.4.1.311.20.2.2'}) #Smart Card Log-on from https://oidref.com/1.3.6.1.4.1.311.20.2.2 and https://www.betaarchive.com/wiki/index.php?title=Microsoft_KB_Archive/287547
$Certificate = ([System.Security.Cryptography.X509Certificates.X509Certificate2UI]::SelectFromCollection($ValidCerts, 'Choose a certificate', 'Choose a certificate', 0))[0]
}
#RSA Specifics
If ($Certificate.PublicKey.Oid.FriendlyName -eq 'RSA') {
$OpenSshPubKey = 'ssh-rsa '
$Algorithm = '00-00-00-07-73-73-68-2d-72-73-61' #ssh-rsa
$RSAPubKey = [System.Security.Cryptography.X509Certificates.RSACertificateExtensions]::GetRSAPublicKey($Certificate)
[xml]$XmlKey = $RSAPubKey.ToXmlString($false)
$ExponentBytes = [System.Convert]::FromBase64String($XmlKey.RSAKeyValue.Exponent)
$Modulus = [System.BitConverter]::ToString([System.Convert]::FromBase64String($XmlKey.RsaKeyValue.Modulus))
}
#DSA Specifics
ElseIf ($Certificate.PublicKey.Oid.FriendlyName -eq 'DSA') {
$OpenSshPubKey = 'ssh-dss '
$Algorithm = '00-00-00-07-73-73-68-2d-64-73-73' #ssh-dss
$DSAPubKey = [System.Security.Cryptography.X509Certificates.DSACertificateExtensions]::GetDSAPublicKey($Certificate)
[xml]$XmlKey = $DSAPubKey.ToXmlString($false)
$ExponentBytes = [System.Convert]::FromBase64String($XmlKey.DSAKeyValue.Exponent)
$Modulus = [System.BitConverter]::ToString([System.Convert]::FromBase64String($XmlKey.DsaKeyValue.Modulus))
}
#ECDsa and Ed25519 do not have the proper types or ToXmlString() in the X509Certificate library
Else {
Throw 'Unsupported key type.'
}
#Key
$ExponentLengthHex = $ExponentBytes.Length.ToString("x8")
$ExponentHex = [System.BitConverter]::ToString($ExponentBytes)
$Exponent = $ExponentLengthHex + $ExponentHex
$KeySize = $Certificate.PublicKey.Key.KeySize
$KeyBytesHex = (($KeySize / 8) + 1).ToString("x8")
$ModBegin = "$KeyBytesHex-00"
$HexKey = ($Algorithm, $Exponent, $ModBegin, $Modulus -join '') -replace '-', ''
$Base64Key = ConvertHex-ToBase64 -HexString $HexKey
$OpenSshPubKey += $Base64Key
#Comment
$OpenSshPubKey += " CAPI:$($Certificate.Thumbprint.ToLower()) $($Certificate.Subject)"
Write-Output $OpenSshPubKey
}