View Javadoc
1   /*
2    * Copyright 2012 Brian Matthews
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 com.btmatthews.maven.plugins.crx;
18  
19  import java.io.File;
20  import java.io.FileNotFoundException;
21  import java.io.IOException;
22  import java.security.GeneralSecurityException;
23  import java.security.KeyFactory;
24  import java.security.PublicKey;
25  import java.security.spec.KeySpec;
26  import java.security.spec.X509EncodedKeySpec;
27  
28  import org.apache.maven.plugin.AbstractMojo;
29  import org.apache.maven.plugin.MojoExecutionException;
30  import org.apache.maven.plugin.MojoFailureException;
31  import org.apache.maven.plugins.annotations.Component;
32  import org.apache.maven.plugins.annotations.LifecyclePhase;
33  import org.apache.maven.plugins.annotations.Mojo;
34  import org.apache.maven.plugins.annotations.Parameter;
35  import org.codehaus.plexus.util.StringUtils;
36  
37  /**
38   * Implement the crx-verify goal for the plug-in. The crx-verify goal verifies the signature of a Chrome Browser
39   * Extension.
40   *
41   * @author <a href="mailto:brian@btmatthews.com">Brian Matthews</a>
42   * @since 1.1.0
43   */
44  @Mojo(name = "crx-verify", defaultPhase = LifecyclePhase.PACKAGE)
45  public class CRXVerifyMojo extends AbstractMojo {
46  
47      /**
48       * The location of the Chrome Extension which is used to override the default location calculated using the
49       * output directory final name and classifier.
50       */
51      @Parameter(required = false)
52      private File crxPath;
53  
54      /**
55       * The final name of the artifact.
56       */
57      @Parameter(defaultValue = "${project.build.finalName}", required = true)
58      private String finalName;
59  
60      /**
61       * The build target directory.
62       */
63      @Parameter(defaultValue = "${project.build.directory}", required = true)
64      private File outputDirectory;
65  
66      /**
67       * An optional classifier for the artifact.
68       */
69      @Parameter
70      private String classifier;
71  
72      /**
73       * The archive helper is used to read the CRX archive.
74       */
75      @Component
76      private ArchiveHelper archiveHelper;
77  
78      /**
79       * The signature helper is used to verify the signature of the CRX archive.
80       */
81      @Component
82      private SignatureHelper signatureHelper;
83  
84      /**
85       * Called when the Maven plug-in is executing. It loads and verifies the signature of a CRX archive.
86       *
87       * @throws MojoExecutionException If there was an error that should stop the build.
88       * @throws MojoFailureException   If there was an error but the build might be allowed to continue.
89       */
90      @Override
91      public final void execute() throws MojoExecutionException, MojoFailureException {
92  
93          final File crxFile;
94  
95          if (crxPath == null) {
96  
97              // Generate CRX file name
98  
99              final StringBuilder crxFilename = new StringBuilder();
100             crxFilename.append(finalName);
101             if (StringUtils.isNotEmpty(classifier)) {
102                 crxFilename.append('-');
103                 crxFilename.append(classifier);
104             }
105             crxFilename.append(".crx");
106             crxFile = new File(outputDirectory, crxFilename.toString());
107         } else {
108             crxFile = crxPath;
109         }
110 
111         try {
112             final CRXArchive archive = archiveHelper.readArchive(crxFile);
113             final KeyFactory keyFactory = KeyFactory.getInstance("RSA");
114             final KeySpec keySpec = new X509EncodedKeySpec(archive.getPublicKey());
115             final PublicKey publicKey = keyFactory.generatePublic(keySpec);
116             if (!signatureHelper.check(archive.getData(), publicKey, archive.getSignature())) {
117                 throw new MojoFailureException("The signature is not valid");
118             }
119         } catch (final FileNotFoundException e) {
120             throw new MojoExecutionException("Could not find CRX archive", e);
121         } catch (final IOException e) {
122             throw new MojoExecutionException("Could not load CRX archive", e);
123         } catch (final GeneralSecurityException e) {
124             throw new MojoExecutionException(e.getMessage(), e);
125         }
126     }
127 }