encryption - How to sign and encrypt a message using S/MIME in PowerShell -
i attempting create powershell script will:
- build message
- sign message using private s/mime certificate
- encrypt message using s/mime public cert of recipient
- send email has been signed , encrypted
i have included full script below changed email addresses, cert names, etc.
the private cert has been imported onto machine using internet explorer. referenced within directory c:\users\xxx\appdata\roaming\microsoft\systemcertificates\my\certificates\
the problem when send email using script being encrypted not signed.
however, if don't encrypt message , instead include $signedmessagebytes
when building memory stream (see first line in step 4 of script) email signed correctly when being sent. suggest message being correctly signed before encryption occurs.
for reason script won't include signature when encrypting message.
what must signature included when message encrypted?
$smtpserver = "localhost" $recipient = "recipient@emailaddress.com" $from = "sender@emailaddress.com" $recipientcertificatepath = "c:\recipient@emailaddress.com.cer" $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 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 , 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)
Comments
Post a Comment