...

Source file src/github.com/sassoftware/relic/signers/vsix/signer.go

Documentation: github.com/sassoftware/relic/signers/vsix

     1  //
     2  // Copyright (c) SAS Institute Inc.
     3  //
     4  // Licensed under the Apache License, Version 2.0 (the "License");
     5  // you may not use this file except in compliance with the License.
     6  // You may obtain a copy of the License at
     7  //
     8  //     http://www.apache.org/licenses/LICENSE-2.0
     9  //
    10  // Unless required by applicable law or agreed to in writing, software
    11  // distributed under the License is distributed on an "AS IS" BASIS,
    12  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    13  // See the License for the specific language governing permissions and
    14  // limitations under the License.
    15  //
    16  
    17  package vsix
    18  
    19  import (
    20  	"archive/zip"
    21  	"errors"
    22  	"io"
    23  	"os"
    24  	"path"
    25  
    26  	"github.com/beevik/etree"
    27  	"github.com/sassoftware/relic/lib/certloader"
    28  	"github.com/sassoftware/relic/lib/magic"
    29  	"github.com/sassoftware/relic/lib/pkcs7"
    30  	"github.com/sassoftware/relic/lib/pkcs9"
    31  	"github.com/sassoftware/relic/lib/xmldsig"
    32  	"github.com/sassoftware/relic/signers"
    33  	"github.com/sassoftware/relic/signers/zipbased"
    34  )
    35  
    36  var Signer = &signers.Signer{
    37  	Name:      "vsix",
    38  	Magic:     magic.FileTypeVSIX,
    39  	CertTypes: signers.CertTypeX509,
    40  	Transform: zipbased.Transform,
    41  	Sign:      sign,
    42  	Verify:    verify,
    43  }
    44  
    45  type zipFiles map[string]*zip.File
    46  
    47  func init() {
    48  	signers.Register(Signer)
    49  	Signer.Flags().Bool("detach-certs", false, "(VSIX) Package certificates separately in the archive")
    50  }
    51  
    52  func sign(r io.Reader, cert *certloader.Certificate, opts signers.SignOpts) ([]byte, error) {
    53  	detachCerts := opts.Flags.GetBool("detach-certs")
    54  	m, err := mangleZip(r, opts.Hash)
    55  	if err != nil {
    56  		return nil, err
    57  	}
    58  	// add rels and origin to zip
    59  	sigName := path.Join(xmlSigPath, calcFileName(cert.Leaf)+".psdsxs")
    60  	if err := m.newRels("", originPath, sigOriginType); err != nil {
    61  		return nil, err
    62  	}
    63  	if err := m.newRels(originPath, sigName, sigType); err != nil {
    64  		return nil, err
    65  	}
    66  	if err := m.addOrigin(); err != nil {
    67  		return nil, err
    68  	}
    69  	// add certs (optional)
    70  	if detachCerts {
    71  		if err := m.addCerts(cert, sigName); err != nil {
    72  			return nil, err
    73  		}
    74  	}
    75  	// sign and add ctypes
    76  	sigfile, err := m.makeSignature(cert, opts, detachCerts)
    77  	if err != nil {
    78  		return nil, err
    79  	}
    80  	if err := m.m.NewFile(sigName, sigfile); err != nil {
    81  		return nil, err
    82  	}
    83  	if err := m.newCtypes(detachCerts); err != nil {
    84  		return nil, err
    85  	}
    86  	patch, err := m.m.MakePatch(true)
    87  	if err != nil {
    88  		return nil, err
    89  	}
    90  	return opts.SetBinPatch(patch)
    91  }
    92  
    93  func verify(f *os.File, opts signers.VerifyOpts) ([]*signers.Signature, error) {
    94  	// read zip file
    95  	size, err := f.Seek(0, io.SeekEnd)
    96  	if err != nil {
    97  		return nil, err
    98  	}
    99  	inz, err := zip.NewReader(f, size)
   100  	if err != nil {
   101  		return nil, err
   102  	}
   103  	files := make(zipFiles, len(inz.File))
   104  	for _, f := range inz.File {
   105  		files[f.Name] = f
   106  	}
   107  	// find and parse the signature XML
   108  	sig, certs, err := readSignature(files)
   109  	if err != nil {
   110  		return nil, err
   111  	}
   112  	doc := etree.NewDocument()
   113  	if err := doc.ReadFromString(string(sig)); err != nil {
   114  		return nil, err
   115  	}
   116  	root := doc.Root()
   117  	// basic verification of XML
   118  	xs, err := xmldsig.Verify(root, ".", certs)
   119  	if err != nil {
   120  		return nil, err
   121  	}
   122  	// verify digests of files
   123  	if err := checkManifest(files, xs.Reference); err != nil {
   124  		return nil, err
   125  	}
   126  	// verify PKCS#9 timestamp token
   127  	cs, err := checkTimestamp(root, xs.EncryptedDigest)
   128  	if err != nil {
   129  		return nil, err
   130  	}
   131  	psig := pkcs7.Signature{Intermediates: xs.Certificates, Certificate: xs.Leaf()}
   132  	if psig.Certificate == nil {
   133  		return nil, errors.New("leaf x509 certificate not found")
   134  	}
   135  	return []*signers.Signature{&signers.Signature{
   136  		Hash: xs.Hash,
   137  		X509Signature: &pkcs9.TimestampedSignature{
   138  			Signature:        psig,
   139  			CounterSignature: cs,
   140  		},
   141  	}}, nil
   142  }
   143  

View as plain text