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 + -
显示快捷键?