smime
来自「支持SSL v2/v3, TLS, PKCS #5, PKCS #7, PKCS」· 代码 · 共 574 行 · 第 1/2 页
TXT
574 行
#!/usr/local/bin/perl# The contents of this file are subject to the Mozilla Public# License Version 1.1 (the "License"); you may not use this file# except in compliance with the License. You may obtain a copy of# the License at http://www.mozilla.org/MPL/# # Software distributed under the License is distributed on an "AS# IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or# implied. See the License for the specific language governing# rights and limitations under the License.# # The Original Code is the Netscape security libraries.# # The Initial Developer of the Original Code is Netscape# Communications Corporation. Portions created by Netscape are # Copyright (C) 1994-2000 Netscape Communications Corporation. All# Rights Reserved.# # Contributor(s):# # Alternatively, the contents of this file may be used under the# terms of the GNU General Public License Version 2 or later (the# "GPL"), in which case the provisions of the GPL are applicable # instead of those above. If you wish to allow use of your # version of this file only under the terms of the GPL and not to# allow others to use your version of this file under the MPL,# indicate your decision by deleting the provisions above and# replace them with the notice and other provisions required by# the GPL. If you do not delete the provisions above, a recipient# may use your version of this file under either the MPL or the# GPL.## smime.pl - frontend for S/MIME message generation and parsing## $Id: smime,v 1.6 2000/07/07 00:57:39 chrisk%netscape.com Exp $#use Getopt::Std;@boundarychars = ( "0" .. "9", "A" .. "F" );# path to cmsutil$cmsutilpath = "cmsutil";## Thanks to Gisle Aas <gisle@aas.no> for the base64 functions# originally taken from MIME-Base64-2.11 at www.cpan.org#sub encode_base64($){ my $res = ""; pos($_[0]) = 0; # ensure start at the beginning while ($_[0] =~ /(.{1,45})/gs) { $res .= substr(pack('u', $1), 1); # get rid of length byte after packing chop($res); } $res =~ tr|` -_|AA-Za-z0-9+/|; # fix padding at the end my $padding = (3 - length($_[0]) % 3) % 3; $res =~ s/.{$padding}$/'=' x $padding/e if $padding; # break encoded string into lines of no more than 76 characters each $res =~ s/(.{1,76})/$1\n/g; $res;}sub decode_base64($){ local($^W) = 0; # unpack("u",...) gives bogus warning in 5.00[123] my $str = shift; my $res = ""; $str =~ tr|A-Za-z0-9+=/||cd; # remove non-base64 chars if (length($str) % 4) { require Carp; Carp::carp("Length of base64 data not a multiple of 4") } $str =~ s/=+$//; # remove padding $str =~ tr|A-Za-z0-9+/| -_|; # convert to uuencoded format while ($str =~ /(.{1,60})/gs) { my $len = chr(32 + length($1)*3/4); # compute length byte $res .= unpack("u", $len . $1 ); # uudecode } $res;}## parse headers into a hash## %headers = parseheaders($headertext);#sub parseheaders($){ my ($headerdata) = @_; my $hdr; my %hdrhash; my $hdrname; my $hdrvalue; my @hdrvalues; my $subhdrname; my $subhdrvalue; # the expression in split() correctly handles continuation lines foreach $hdr (split(/\n(?=\S)/, $headerdata)) { $hdr =~ s/\r*\n\s+/ /g; # collapse continuation lines ($hdrname, $hdrvalue) = $hdr =~ m/^(\S+):\s+(.*)$/; # ignore non-headers (or should we die horribly?) next unless (defined($hdrname)); $hdrname =~ tr/A-Z/a-z/; # lowercase the header name @hdrvalues = split(/\s*;\s*/, $hdrvalue); # split header values (XXXX quoting) # there is guaranteed to be at least one value $hdrvalue = shift @hdrvalues; if ($hdrvalue =~ /^\s*\"(.*)\"\s*$/) { # strip quotes if there $hdrvalue = $1; } $hdrhash{$hdrname}{MAIN} = $hdrvalue; # print "XXX $hdrname = $hdrvalue\n"; # deal with additional name-value pairs foreach $hdrvalue (@hdrvalues) { ($subhdrname, $subhdrvalue) = $hdrvalue =~ m/^(\S+)\s*=\s*(.*)$/; # ignore non-name-value pairs (or should we die?) next unless (defined($subhdrname)); $subhdrname =~ tr/A-Z/a-z/; if ($subhdrvalue =~ /^\s*\"(.*)\"\s*$/) { # strip quotes if there $subhdrvalue = $1; } $hdrhash{$hdrname}{$subhdrname} = $subhdrvalue; } } return %hdrhash;}## encryptentity($entity, $options) - encrypt an S/MIME entity,# creating a new application/pkcs7-smime entity## entity - string containing entire S/MIME entity to encrypt# options - options for cmsutil## this will generate and return a new application/pkcs7-smime entity containing# the enveloped input entity.#sub encryptentity($$){ my ($entity, $cmsutiloptions) = @_; my $out = ""; my $boundary; $tmpencfile = "/tmp/encryptentity.$$"; # # generate a random boundary string # $boundary = "------------ms" . join("", @boundarychars[map{rand @boundarychars }( 1 .. 24 )]); # # tell cmsutil to generate a enveloped CMS message using our data # open(CMS, "|$cmsutilpath -E $cmsutiloptions -o $tmpencfile") or die "ERROR: cannot pipe to cmsutil"; print CMS $entity; unless (close(CMS)) { print STDERR "ERROR: encryption failed.\n"; unlink($tmpsigfile); exit 1; } $out = "Content-Type: application/pkcs7-mime; smime-type=enveloped-data; name=smime.p7m\n"; $out .= "Content-Transfer-Encoding: base64\n"; $out .= "Content-Disposition: attachment; filename=smime.p7m\n"; $out .= "\n"; # end of entity header open (ENC, $tmpencfile) or die "ERROR: cannot find newly generated encrypted content"; local($/) = undef; # slurp whole file $out .= encode_base64(<ENC>), "\n"; # entity body is base64-encoded CMS message close(ENC); unlink($tmpencfile); $out;}## signentity($entity, $options) - sign an S/MIME entity## entity - string containing entire S/MIME entity to sign# options - options for cmsutil## this will generate and return a new multipart/signed entity consisting# of the canonicalized original content, plus a signature block.#sub signentity($$){ my ($entity, $cmsutiloptions) = @_; my $out = ""; my $boundary; $tmpsigfile = "/tmp/signentity.$$"; # # generate a random boundary string # $boundary = "------------ms" . join("", @boundarychars[map{rand @boundarychars }( 1 .. 24 )]); # # tell cmsutil to generate a signed CMS message using the canonicalized data # The signedData has detached content (-T) and includes a signing time attribute (-G) # # if we do not provide a password on the command line, here's where we would be asked for it # open(CMS, "|$cmsutilpath -S -T -G $cmsutiloptions -o $tmpsigfile") or die "ERROR: cannot pipe to cmsutil"; print CMS $entity; unless (close(CMS)) { print STDERR "ERROR: signature generation failed.\n"; unlink($tmpsigfile); exit 1; } open (SIG, $tmpsigfile) or die "ERROR: cannot find newly generated signature"; # # construct a new multipart/signed MIME entity consisting of the original content and # the signature # # (we assume that cmsutil generates a SHA1 digest) $out .= "Content-Type: multipart/signed; protocol=\"application/pkcs7-signature\"; micalg=sha1; boundary=\"${boundary}\"\n"; $out .= "\n"; # end of entity header $out .= "This is a cryptographically signed message in MIME format.\n"; # explanatory comment $out .= "\n--${boundary}\n"; $out .= $entity; $out .= "\n--${boundary}\n"; $out .= "Content-Type: application/pkcs7-signature; name=smime.p7s\n"; $out .= "Content-Transfer-Encoding: base64\n"; $out .= "Content-Disposition: attachment; filename=smime.p7s\n"; $out .= "Content-Description: S/MIME Cryptographic Signature\n"; $out .= "\n"; # end of signature subentity header local($/) = undef; # slurp whole file $out .= encode_base64(<SIG>); # append base64-encoded signature $out .= "\n--${boundary}--\n"; close(SIG); unlink($tmpsigfile); $out;}sub usage { print STDERR "usage: smime [options]\n"; print STDERR " options:\n"; print STDERR " -S nick generate signed message, use certificate named \"nick\"\n"; print STDERR " -p passwd use \"passwd\" as security module password\n"; print STDERR " -E rec1[,rec2...] generate encrypted message for recipients\n"; print STDERR " -D decode a S/MIME message\n"; print STDERR " -C pathname set pathname of \"cmsutil\"\n"; print STDERR " -d directory set directory containing certificate db\n"; print STDERR " (default: ~/.netscape)\n"; print STDERR "\nWith -S or -E, smime will take a regular RFC822 message or MIME entity\n"; print STDERR "on stdin and generate a signed or encrypted S/MIME message with the same\n"; print STDERR "headers and content from it. The output can be used as input to a MTA.\n"; print STDERR "-D causes smime to strip off all S/MIME layers if possible and output\n"; print STDERR "the \"inner\" message.\n";}## start of main procedures### process command line options#unless (getopts('S:E:p:d:C:D')) { usage(); exit 1;}unless (defined($opt_S) or defined($opt_E) or defined($opt_D)) { print STDERR "ERROR: -S and/or -E, or -D must be specified.\n"; usage(); exit 1;}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?