Skip to content

Instantly share code, notes, and snippets.

@SP3269
Created January 5, 2018 05:53
Show Gist options
  • Save SP3269/b852ddfe1319840ada2be0120a910132 to your computer and use it in GitHub Desktop.
Save SP3269/b852ddfe1319840ada2be0120a910132 to your computer and use it in GitHub Desktop.
JWT verification in Powershell - prototype
# JWT signature verification
# $jwt should contain the JWT as a string
$parts = $jwt.Split('.')
$SHA256 = New-Object Security.Cryptography.SHA256Managed
$computed = $SHA256.ComputeHash([System.Text.Encoding]::UTF8.GetBytes($parts[0]+"."+$parts[1]))
# Method A - just using X509Certificate2. TODO: initialise from file, no private key
# Reference: https://blogs.msdn.microsoft.com/alejacma/2008/06/25/how-to-sign-and-verify-the-signature-with-net-and-a-certificate-c/
$certx = New-Object System.Security.Cryptography.X509Certificates.X509Certificate2
$certx.Import("c:\ps\jwt\jwt.cer") # Usually available; reading from file here
$signed = $parts[2].replace('-','+').replace('_','/') # Decoding Base64url to the original byte array
$mod = $signed.Length % 4
switch ($mod) {
0 { $signed = $signed }
1 { $signed = $signed.Substring(0,$signedToDecode.Length-1) }
2 { $signed = $signed + "==" }
3 { $signed = $signed + "=" }
} # Done
$bytes = [Convert]::FromBase64String($signed)
$certx.PublicKey.Key.VerifyHash($computed,"SHA256",$bytes)
# Method B - using RSAPKCS1SignatureDeformatter and RSA parameters (modulus and exponent - both public)
# Good reference at https://www.iuliantabara.com/tag/rsapkcs1signatureformatter/
# Also https://stackoverflow.com/questions/34403823/verifying-jwt-signed-with-the-rs256-algorithm-using-public-key-in-c-sharp
$cert = New-Object System.Security.Cryptography.X509Certificates.X509Certificate2
$cert.import("c:\ps\jwt\jwt.pfx","jwt","Exportable,PersistKeySet")
# Here's how to get the RSA parameters; only m_public is needed to get the key exponent and modulus for signature verification - should be available
# Of course, same parameters are available in the certificate file - parse at your leisure
$rsacsp = $cert.PrivateKey
$m_public = $rsacsp.ExportParameters($false);
$m_private = $rsacsp.ExportParameters($true);
# Run using the parameters
$rsacsp1 = New-Object System.Security.Cryptography.RSACryptoServiceProvider
$rsakeyinfo = New-Object System.Security.Cryptography.RSAParameters
$rsakeyinfo.Modulus = $m_public.Modulus
$rsakeyinfo.Exponent = $m_public.Exponent
$rsacsp1.ImportParameters($rsakeyinfo)
$df = New-Object System.Security.Cryptography.RSAPKCS1SignatureDeformatter($rsacsp1)
$df.SetHashAlgorithm("SHA256")
$signed = $parts[2].replace('-','+').replace('_','/') # Decoding Base64url to the original byte array
$mod = $signed.Length % 4
switch ($mod) {
0 { $signed = $signed }
1 { $signed = $signed.Substring(0,$signedToDecode.Length-1) }
2 { $signed = $signed + "==" }
3 { $signed = $signed + "=" }
}
$bytes = [Convert]::FromBase64String($signed)
$df.VerifySignature($computed,$bytes)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment