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

Popular posts from this blog

networking - Vagrant-provisioned VirtualBox VM is not reachable from Ubuntu host -

c# - ASP.NET Core - There is already an object named 'AspNetRoles' in the database -

ruby on rails - ArgumentError: Missing host to link to! Please provide the :host parameter, set default_url_options[:host], or set :only_path to true -