Private/x509/New-Pkcs7SignedMessage.ps1
<#
.SYNOPSIS Signs a message using the PKCS#7 signed data format. .DESCRIPTION Signs a message using the PKCS#7 signed data format. The message is signed using the private key of the signer certificate. Additional attributes are added to the signed message to comply with RFC 8894 (SCEP PKIMessage). https://www.rfc-editor.org/rfc/rfc8894.html#name-scep-pkimessage .PARAMETER SignerCertificate The certificate of the signer. .PARAMETER Message The message to sign. .OUTPUTS Byte[] The signed message. .EXAMPLE $SignerCertificate = Get-ChildItem -Path 'Cert:\CurrentUser\My' | Where-Object { $_.Subject -eq 'CN=Signer' } $Message = [System.Text.Encoding]::UTF8.GetBytes('Hello, World!') $SignedMessage = New-Pkcs7SignedMessage -SignerCertificate $SignerCertificate -Message $Message #> Function New-Pkcs7SignedMessage { [CmdletBinding()] Param( [Parameter(Mandatory)] [System.Security.Cryptography.X509Certificates.X509Certificate2]$SignerCertificate, [Parameter(Mandatory)] [Byte[]]$Message ) Write-Verbose "$($MyInvocation.MyCommand): Signing message using $($SignerCertificate.Subject)" $CmsSigner = [System.Security.Cryptography.Pkcs.CmsSigner]::new($SignerCertificate) $CmsSigner.DigestAlgorithm = $constant_MD5Oid $MessageTypeBody = ([System.Text.Encoding]::ASCII).GetBytes('17') $MessageTypeHeader = [Byte[]]@([Byte]19, [Byte]$MessageTypeBody.Length) $MessageTypeData = $MessageTypeHeader + $MessageTypeBody $MessageTypeAttribute = [System.Security.Cryptography.AsnEncodedData]::new($constant_MessageTypeOid, $MessageTypeData) $CmsSigner.SignedAttributes.Add($MessageTypeAttribute) | Out-Null $Sha = New-Object System.Security.Cryptography.SHA512Managed $HashedKey = $Sha.ComputeHash($SignerCertificate.GetPublicKey()) $HashedKeyString = [System.Convert]::ToBase64String($HashedKey) $TransactionIdBody = ([System.Text.Encoding]::ASCII).GetBytes($HashedKeyString) $TransactionIdHeader = [Byte[]]@([Byte]19, [Byte]$TransactionIdBody.Length) $TransactionIdData = $TransactionIdHeader + $TransactionIdBody $TransactionIdAttribute = [System.Security.Cryptography.Pkcs.Pkcs9AttributeObject]::new($constant_TransactionIdOid, $TransactionIdData) $CmsSigner.SignedAttributes.Add($TransactionIdAttribute) | Out-Null $LastSenderNonce = New-Object Byte[] 16 [System.Security.Cryptography.RNGCryptoServiceProvider]::Create().GetBytes($LastSenderNonce) $SenderNonceHeader = [Byte[]]@([Byte]4, [Byte]$LastSenderNonce.Length) $SenderNonceData = $SenderNonceHeader + $LastSenderNonce $SenderNonceAttribute = [System.Security.Cryptography.Pkcs.Pkcs9AttributeObject]::new($constant_SenderNonceOid, $SenderNonceData) $CmsSigner.SignedAttributes.Add($SenderNonceAttribute) | Out-Null $SignedContentInfo = [System.Security.Cryptography.Pkcs.ContentInfo]::new($Message) $SignedMessage = [System.Security.Cryptography.Pkcs.SignedCms]::new($SignedContentInfo) $SignedMessage.ComputeSignature($CmsSigner) Return $SignedMessage.Encode() } |