Je cherche à créer un script PowerShell qui:Comment signer et chiffrer un message en utilisant S/MIME dans PowerShell
- Construire un message
- Signer le message en utilisant mon certificat privé S/MIME
- Chiffrer le message en utilisant le cert publique S/MIME du destinataire
- Envoyer l'e-mail qui a été signé et chiffré
I ont inclus le script complet ci-dessous, mais ont changé d'adresse e-mail, de nom de certificat, etc.
Le certificat privé a été importé sur la machine à l'aide d'Internet Explorer. Il est ensuite référencé dans le répertoire C:\Users\xxx\AppData\Roaming\Microsoft\SystemCertificates\My\Certificates\
Le problème est que lorsque j'envoie l'email en utilisant le script, il est crypté mais pas signé.
Toutefois, si je ne crypte pas le message et que j'inclue $SignedMessageBytes
lors de la création du flux de mémoire (voir la première ligne à l'étape 4 du script), l'e-mail est correctement signé lors de l'envoi. Cela suggère que le message est correctement signé avant le cryptage.
Pour une raison quelconque, le script n'inclura pas la signature lors du cryptage du message.
Que dois-je faire pour que la signature soit incluse lorsque le message est crypté?
$SMTPServer = "localhost"
$Recipient = "[email protected]"
$From = "[email protected]"
$RecipientCertificatePath = "C:\[email protected]"
$SignerCertificatePath = "C:\Users\xxx\AppData\Roaming\Microsoft\SystemCertificates\My\Certificates\xxxx"
Add-Type -assemblyName "System.Security"
$MailClient = New-Object System.Net.Mail.SmtpClient $SMTPServer
$Message = New-Object System.Net.Mail.MailMessage
$Message.To.Add($Recipient)
$Message.From = $From
$Body = $null
$File= get-item -Path "C:\CONTRL__9911837000009_4045399000008_20170704_ELE00207.TXT"
$Message.Subject = $File.Name
# STEP 1: Capture Message Body
$MIMEMessage = New-Object system.Text.StringBuilder
$MIMEMessage.AppendLine("MIME-Version: 1.0") | Out-Null
$MIMEMessage.AppendLine("Content-Type: multipart/mixed; boundary=unique-boundary-1") | Out-Null
$MIMEMessage.AppendLine() | Out-Null
$MIMEMessage.AppendLine("This is a multi-part message in MIME format.") | Out-Null
$MIMEMessage.AppendLine("--unique-boundary-1") | Out-Null
$MIMEMessage.AppendLine("Content-Type: text/plain") | Out-Null
$MIMEMessage.AppendLine("Content-Transfer-Encoding: 7Bit") | Out-Null
$MIMEMessage.AppendLine() | Out-Null
$MIMEMessage.AppendLine($Body) | Out-Null
$MIMEMessage.AppendLine() | Out-Null
$MIMEMessage.AppendLine("--unique-boundary-1") | Out-Null
$MIMEMessage.AppendLine("Content-Type: application/octet-stream; name="+ $file.Name) | Out-Null
$MIMEMessage.AppendLine("Content-Transfer-Encoding: base64") | Out-Null
$MIMEMessage.AppendLine("Content-Disposition: attachment; filename="+ $file.Name) | Out-Null
$MIMEMessage.AppendLine() | Out-Null
[Byte[]] $binaryData = [System.IO.File]::ReadAllBytes($File)
[string] $base64Value = [System.Convert]::ToBase64String($binaryData, 0, $binaryData.Length)
[int] $position = 0
while($position -lt $base64Value.Length)
{
[int] $chunkSize = 100
if (($base64Value.Length - ($position + $chunkSize)) -lt 0)
{
$chunkSize = $base64Value.Length - $position
}
$MIMEMessage.AppendLine($base64Value.Substring($position, $chunkSize)) | Out-Null
$MIMEMessage.AppendLine() | Out-Null
$position += $chunkSize;
}
$MIMEMessage.AppendLine("--unique-boundary-1--") | Out-Null
[Byte[]] $MessageBytes = [System.Text.Encoding]::ASCII.GetBytes($MIMEMessage.ToString())
# STEP 2: Sign
$ci = New-Object System.Security.Cryptography.Pkcs.ContentInfo(,$MessageBytes)
$signedCms = New-Object System.Security.Cryptography.Pkcs.SignedCms($ci)
$SignerCertificate = New-Object System.Security.Cryptography.X509Certificates.X509Certificate2($SignerCertificatePath)
$Signer = New-Object System.Security.Cryptography.Pkcs.CmsSigner($SignerCertificate)
$timeAttribute = New-Object -TypeName System.Security.Cryptography.Pkcs.Pkcs9SigningTime
$null = $signer.SignedAttributes.Add($timeAttribute)
$sha2_oid = New-Object System.Security.Cryptography.Oid("2.16.840.1.101.3.4.2.1")
$Signer.DigestAlgorithm = $sha2_oid
Write-Host "-----------------------------------------------------"
Write-Host "Cert friendly name: " $Signer.Certificate.FriendlyName
Write-Host "Cert subject : " $Signer.Certificate.Subject
Write-Host "Cert thumbprint : " $Signer.Certificate.Thumbprint
Write-Host "Digest algorithm : " $Signer.DigestAlgorithm.FriendlyName
Write-Host "Sign Time : " $Signer.SignedAttributes.Values.SigningTime
$signedCms.ComputeSignature($Signer)
$SignedMessageBytes = $signedCms.Encode()
# STEP 3: Encrypt
$ContentInfo = New-Object System.Security.Cryptography.Pkcs.ContentInfo (,$SignedMessageBytes)
$CMSRecipient = New-Object System.Security.Cryptography.Pkcs.CmsRecipient $RecipientCertificatePath
$algo_id = New-Object System.Security.Cryptography.Pkcs.AlgorithmIdentifier("2.16.840.1.101.3.4.1.42")
$EnvelopedCMS = New-Object System.Security.Cryptography.Pkcs.EnvelopedCms($ContentInfo , $algo_id)
$EnvelopedCMS.Encrypt($CMSRecipient)
Write-Host "Key length : " $EnvelopedCMS.ContentEncryptionAlgorithm.KeyLength
Write-Host "OID friendly name: " $EnvelopedCMS.ContentEncryptionAlgorithm.Oid.FriendlyName
Write-Host "OID value : " $EnvelopedCMS.ContentEncryptionAlgorithm.Oid.Value
Write-Host "Parameters : " $EnvelopedCMS.ContentEncryptionAlgorithm.Parameters
[Byte[]] $EncryptedBytes = $EnvelopedCMS.Encode()
# STEP 4: Create and send mail
$MemoryStream = New-Object System.IO.MemoryStream @(,$EncryptedBytes)
$AlternateView = New-Object System.Net.Mail.AlternateView($MemoryStream, "application/x-pkcs7-mime; smime-type=enveloped-data;name=smime.p7m")
$Message.AlternateViews.Add($AlternateView)
$MailClient.Send($Message)
@abil C'est fantastique. Merci pour ça. Y a-t-il une chance que vous puissiez convertir pour qu'il crypte d'abord et ensuite signe (plutôt que de signer et crypter). J'ai essayé mais j'ai fini avec plusieurs couches de cryptage et de signature et cela n'a pas fonctionné. – gerard