Fix the ECDSA signature issue for PowerShellSDK (#7386)

* Fix the ECDSA signature issue for PowerShellSDK

* updated the sample for ECDSA HTTPSigning

* fix the sample doc
This commit is contained in:
Ghufz 2020-09-11 10:05:44 +05:30 committed by GitHub
parent df441fe2ee
commit 00e20ffb2c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 108 additions and 22 deletions

View File

@ -237,7 +237,7 @@ function Get-{{{apiNamePrefix}}}ECDSASignature {
}
if ($PSVersionTable.PSVersion.Major -lt 7) {
throw "ECDSA key is not supported on $($PSVersionTable.PSVersion), Use PSVersion 7.0 and above"
throw "ECDSA key is not supported on PowerShell version $($PSVersionTable.PSVersion), Use PowerShell v7.0 and above"
}
$ecKeyHeader = "-----BEGIN EC PRIVATE KEY-----"
@ -245,10 +245,8 @@ function Get-{{{apiNamePrefix}}}ECDSASignature {
$keyStr = Get-Content -Path $ECKeyFilePath -Raw
$ecKeyBase64String = $keyStr.Replace($ecKeyHeader, "").Replace($ecKeyFooter, "").Trim()
$keyBytes = [System.Convert]::FromBase64String($ecKeyBase64String)
$ecdsa = [System.Security.Cryptography.ECDsa]::Create()
#$cngKey = [System.Security.Cryptography.CngKey]::Import($keyBytes,[System.Security.Cryptography.CngKeyBlobFormat]::Pkcs8PrivateBlob)
#$ecdsa = [System.Security.Cryptography.ECDsaCng]::New($cngKey)
$ecdsa = [System.Security.Cryptography.ECDsaCng]::New()
[int]$bytCount =0
if (![string]::IsNullOrEmpty($KeyPassPhrase)) {
$ecdsa.ImportEncryptedPkcs8PrivateKey($KeyPassPhrase,$keyBytes,[ref]$bytCount)
@ -256,14 +254,9 @@ function Get-{{{apiNamePrefix}}}ECDSASignature {
$ecdsa.ImportPkcs8PrivateKey($keyBytes,[ref]$bytCount)
}
if ($HashAlgorithmName -eq "sha512") {
$ecdsa.HashAlgorithm = [System.Security.Cryptography.CngAlgorithm]::Sha512
} else {
$ecdsa.HashAlgorithm = [System.Security.Cryptography.CngAlgorithm]::Sha256
}
$signedBytes = $ecdsa.SignHash($DataToSign)
$signedString = [System.Convert]::ToBase64String($signedBytes)
$derBytes = ConvertTo-ECDSAANS1Format -RawBytes $signedBytes
$signedString = [System.Convert]::ToBase64String($derBytes)
return $signedString
}
@ -385,3 +378,53 @@ function Get-{{{apiNamePrefix}}}KeyTypeFromFile {
}
return $keyType
}
<#
.Synopsis
Converts sequence of R and S bytes to ANS1 format for ECDSASIgnature.
.Description
Converts sequence of R and S bytes to ANS1 format for ECDSASIgnature.
.Parameter RawBytes[]
Specifies the R and S bytes of ECDSA signature.
.Outputs
Byte[]
#>
function ConvertTo-ECDSAANS1Format{
Param(
[Parameter(Mandatory = $true)]
[byte[]]$RawBytes
)
$derLength = 68 #default lenght for ECDSA code signinged bit 0x44
$rbytesLength = 32 #R length 0x20
$sbytesLength = 32 #S length 0x20
[byte[]]$rBytes = $signedBytes[0..31]
[byte[]]$sBytes = $signedBytes[32..63]
if($rBytes[0] -gt 0x7F){
$derLength++
$rbytesLength++
$rBytes = [byte[]]@(0x00) + $rBytes
}
if($sBytes[0] -gt 0x7F){
$derLength++
$sbytesLength++
$sBytes = [byte[]]@(0x00) + $sBytes
}
[byte[]]$derBytes = @()
$derBytes += 48 # start of the sequence 0x30
$derBytes += $derLength # total length r lenth, type and r bytes
$derBytes += 2 # tag for integer
$derBytes += $rbytesLength # length of r
$derBytes += $rBytes
$derBytes += 2 #tag for integer
$derBytes += $sbytesLength #length of s
$derBytes += $sBytes
return $derBytes
}

View File

@ -243,7 +243,7 @@ function Get-PSECDSASignature {
}
if ($PSVersionTable.PSVersion.Major -lt 7) {
throw "ECDSA key is not supported on $($PSVersionTable.PSVersion), Use PSVersion 7.0 and above"
throw "ECDSA key is not supported on PowerShell version $($PSVersionTable.PSVersion), Use PowerShell v7.0 and above"
}
$ecKeyHeader = "-----BEGIN EC PRIVATE KEY-----"
@ -251,10 +251,8 @@ function Get-PSECDSASignature {
$keyStr = Get-Content -Path $ECKeyFilePath -Raw
$ecKeyBase64String = $keyStr.Replace($ecKeyHeader, "").Replace($ecKeyFooter, "").Trim()
$keyBytes = [System.Convert]::FromBase64String($ecKeyBase64String)
$ecdsa = [System.Security.Cryptography.ECDsa]::Create()
#$cngKey = [System.Security.Cryptography.CngKey]::Import($keyBytes,[System.Security.Cryptography.CngKeyBlobFormat]::Pkcs8PrivateBlob)
#$ecdsa = [System.Security.Cryptography.ECDsaCng]::New($cngKey)
$ecdsa = [System.Security.Cryptography.ECDsaCng]::New()
[int]$bytCount =0
if (![string]::IsNullOrEmpty($KeyPassPhrase)) {
$ecdsa.ImportEncryptedPkcs8PrivateKey($KeyPassPhrase,$keyBytes,[ref]$bytCount)
@ -262,14 +260,9 @@ function Get-PSECDSASignature {
$ecdsa.ImportPkcs8PrivateKey($keyBytes,[ref]$bytCount)
}
if ($HashAlgorithmName -eq "sha512") {
$ecdsa.HashAlgorithm = [System.Security.Cryptography.CngAlgorithm]::Sha512
} else {
$ecdsa.HashAlgorithm = [System.Security.Cryptography.CngAlgorithm]::Sha256
}
$signedBytes = $ecdsa.SignHash($DataToSign)
$signedString = [System.Convert]::ToBase64String($signedBytes)
$derBytes = ConvertTo-ECDSAANS1Format -RawBytes $signedBytes
$signedString = [System.Convert]::ToBase64String($derBytes)
return $signedString
}
@ -391,3 +384,53 @@ function Get-PSKeyTypeFromFile {
}
return $keyType
}
<#
.Synopsis
Converts sequence of R and S bytes to ANS1 format for ECDSASIgnature.
.Description
Converts sequence of R and S bytes to ANS1 format for ECDSASIgnature.
.Parameter RawBytes[]
Specifies the R and S bytes of ECDSA signature.
.Outputs
Byte[]
#>
function ConvertTo-ECDSAANS1Format{
Param(
[Parameter(Mandatory = $true)]
[byte[]]$RawBytes
)
$derLength = 68 #default lenght for ECDSA code signinged bit 0x44
$rbytesLength = 32 #R length 0x20
$sbytesLength = 32 #S length 0x20
[byte[]]$rBytes = $signedBytes[0..31]
[byte[]]$sBytes = $signedBytes[32..63]
if($rBytes[0] -gt 0x7F){
$derLength++
$rbytesLength++
$rBytes = [byte[]]@(0x00) + $rBytes
}
if($sBytes[0] -gt 0x7F){
$derLength++
$sbytesLength++
$sBytes = [byte[]]@(0x00) + $sBytes
}
[byte[]]$derBytes = @()
$derBytes += 48 # start of the sequence 0x30
$derBytes += $derLength # total length r lenth, type and r bytes
$derBytes += 2 # tag for integer
$derBytes += $rbytesLength # length of r
$derBytes += $rBytes
$derBytes += 2 #tag for integer
$derBytes += $sbytesLength #length of s
$derBytes += $sBytes
return $derBytes
}