// Loads one of the built-in keys (media, platform, shared, testkey) public void loadKeys(String name) throws IOException, GeneralSecurityException { keySet = loadedKeys.get(name); if (keySet != null) return; keySet = new KeySet(); keySet.setName(name); loadedKeys.put(name, keySet); if (KEY_NONE.equals(name)) return; progressHelper.progress(ProgressEvent.PRORITY_IMPORTANT, "Loading certificate and private key"); // load the private key URL privateKeyUrl = getClass().getResource("/keys/" + name + ".pk8"); keySet.setPrivateKey(readPrivateKey(privateKeyUrl, null)); // load the certificate URL publicKeyUrl = getClass().getResource("/keys/" + name + ".x509.pem"); keySet.setPublicKey(readPublicKey(publicKeyUrl)); // load the signature block template URL sigBlockTemplateUrl = getClass().getResource("/keys/" + name + ".sbt"); if (sigBlockTemplateUrl != null) { keySet.setSigBlockTemplate(readContentAsBytes(sigBlockTemplateUrl)); } }
public static boolean hasProjectSpecificSettings(IScopeContext context, KeySet[] keySets) { for (int i = 0; i < keySets.length; i++) { KeySet keySet = keySets[i]; IEclipsePreferences preferences = context.getNode(keySet.getNodeName()); for (final Iterator<String> keyIter = keySet.getKeys().iterator(); keyIter.hasNext(); ) { final String key = keyIter.next(); Object val = preferences.get(key, null); if (val != null) { return true; } } } return false; }
@Override public boolean isCanonical() { for (ThrowConstraint c : throwConstraints) { if (!c.isCanonical()) { return false; } } if (!entryKeys.isCanonical()) { return false; } if (returnKeys != null && !returnKeys.isCanonical()) { return false; } return super.isCanonical(); }
/** * Only to read project specific settings to find out to what profile it matches. * * @param context The project context */ private Map<String, String> readFromPreferenceStore( IScopeContext context, Profile workspaceProfile) { final Map<String, String> profileOptions = new HashMap<String, String>(); IEclipsePreferences uiPrefs = context.getNode(JavaUI.ID_PLUGIN); int version = uiPrefs.getInt(fProfileVersionKey, fProfileVersioner.getFirstVersion()); if (version != fProfileVersioner.getCurrentVersion()) { Map<String, String> allOptions = new HashMap<String, String>(); for (int i = 0; i < fKeySets.length; i++) { addAll(context.getNode(fKeySets[i].getNodeName()), allOptions); } CustomProfile profile = new CustomProfile( "tmp", allOptions, version, fProfileVersioner.getProfileKind()); // $NON-NLS-1$ fProfileVersioner.update(profile); return profile.getSettings(); } boolean hasValues = false; for (int i = 0; i < fKeySets.length; i++) { KeySet keySet = fKeySets[i]; IEclipsePreferences preferences = context.getNode(keySet.getNodeName()); for (final Iterator<String> keyIter = keySet.getKeys().iterator(); keyIter.hasNext(); ) { final String key = keyIter.next(); String val = preferences.get(key, null); if (val != null) { hasValues = true; } else { val = workspaceProfile.getSettings().get(key); } profileOptions.put(key, val); } } if (!hasValues) { return null; } setLatestCompliance(profileOptions); return profileOptions; }
/** * Sign the and signature block template. The signature block template parameter may be null, but * if so android-sun-jarsign-support.jar must be in the classpath. */ public void signZip( Map<String, ZioEntry> zioEntries, OutputStream outputStream, String outputZipFilename) throws IOException, GeneralSecurityException { boolean debug = getLogger().isDebugEnabled(); progressHelper.initProgress(); if (keySet == null) { if (!keymode.startsWith(MODE_AUTO)) throw new IllegalStateException("No keys configured for signing the file!"); // Auto-determine which keys to use String keyName = this.autoDetectKey(keymode, zioEntries); if (keyName == null) throw new AutoKeyException( "Unable to auto-select key for signing " + new File(outputZipFilename).getName()); autoKeyObservable.notifyObservers(keyName); loadKeys(keyName); } ZipOutput zipOutput = null; try { zipOutput = new ZipOutput(outputStream); if (KEY_NONE.equals(keySet.getName())) { progressHelper.setProgressTotalItems(zioEntries.size()); progressHelper.setProgressCurrentItem(0); copyFiles(zioEntries, zipOutput); return; } // Calculate total steps to complete for accurate progress percentages. int progressTotalItems = 0; for (ZioEntry entry : zioEntries.values()) { String name = entry.getName(); if (!entry.isDirectory() && !name.equals(JarFile.MANIFEST_NAME) && !name.equals(CERT_SF_NAME) && !name.equals(CERT_RSA_NAME) && (stripPattern == null || !stripPattern.matcher(name).matches())) { progressTotalItems += 3; // digest for manifest, digest in sig file, copy data } } progressTotalItems += 1; // CERT.RSA generation progressHelper.setProgressTotalItems(progressTotalItems); progressHelper.setProgressCurrentItem(0); // Assume the certificate is valid for at least an hour. long timestamp = keySet.getPublicKey().getNotBefore().getTime() + 3600L * 1000; // MANIFEST.MF // progress(ProgressEvent.PRORITY_NORMAL, JarFile.MANIFEST_NAME); Manifest manifest = addDigestsToManifest(zioEntries); if (canceled) return; ZioEntry ze = new ZioEntry(JarFile.MANIFEST_NAME); ze.setTime(timestamp); manifest.write(ze.getOutputStream()); zipOutput.write(ze); // CERT.SF // progress( ProgressEvent.PRORITY_NORMAL, CERT_SF_NAME); // Can't use default Signature on Android. Although it generates a signature that can be // verified by jarsigner, // the recovery program appears to require a specific algorithm/mode/padding. So we use the // custom ZipSignature instead. // Signature signature = Signature.getInstance("SHA1withRSA"); ZipSignature signature = new ZipSignature(); signature.initSign(keySet.getPrivateKey()); // if (getLogger().isDebugEnabled()) { // getLogger().debug(String.format("Signature provider=%s, alg=%s, class=%s", // signature.getProvider().getName(), // signature.getAlgorithm(), // signature.getClass().getName())); // } ze = new ZioEntry(CERT_SF_NAME); ze.setTime(timestamp); ByteArrayOutputStream out = new ByteArrayOutputStream(); generateSignatureFile(manifest, out); if (canceled) return; byte[] sfBytes = out.toByteArray(); if (debug) { getLogger() .debug( "Signature File: \n" + new String(sfBytes) + "\n" + HexDumpEncoder.encode(sfBytes)); } ze.getOutputStream().write(sfBytes); zipOutput.write(ze); signature.update(sfBytes); byte[] signatureBytes = signature.sign(); if (debug) { MessageDigest md = MessageDigest.getInstance("SHA1"); md.update(sfBytes); byte[] sfDigest = md.digest(); getLogger().debug("Sig File SHA1: \n" + HexDumpEncoder.encode(sfDigest)); getLogger().debug("Signature: \n" + HexDumpEncoder.encode(signatureBytes)); Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding"); cipher.init(Cipher.DECRYPT_MODE, keySet.getPublicKey()); byte[] tmpData = cipher.doFinal(signatureBytes); getLogger().debug("Signature Decrypted: \n" + HexDumpEncoder.encode(tmpData)); // getLogger().debug( "SHA1 ID: \n" + // HexDumpEncoder.encode(AlgorithmId.get("SHA1").encode())); // // Compute signature using low-level APIs. // byte[] beforeAlgorithmIdBytes = { 0x30, 0x21 }; // // byte[] algorithmIdBytes = {0x30, 0x09, 0x06, 0x05, 0x2B, 0x0E, 0x03, // 0x02, 0x1A, 0x05, 0x00 }; // byte[] algorithmIdBytes = AlgorithmId.get("SHA1").encode(); // byte[] afterAlgorithmIdBytes = { 0x04, 0x14 }; // cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding"); // cipher.init(Cipher.ENCRYPT_MODE, privateKey); // getLogger().debug( "Cipher: " + cipher.getAlgorithm() + ", blockSize = " + // cipher.getBlockSize()); // // cipher.update( beforeAlgorithmIdBytes); // cipher.update( algorithmIdBytes); // cipher.update( afterAlgorithmIdBytes); // cipher.update( sfDigest); // byte[] tmpData2 = cipher.doFinal(); // getLogger().debug( "Signature : \n" + HexDumpEncoder.encode(tmpData2)); } // CERT.RSA progressHelper.progress(ProgressEvent.PRORITY_NORMAL, "Generating signature block file"); ze = new ZioEntry(CERT_RSA_NAME); ze.setTime(timestamp); writeSignatureBlock( keySet.getSigBlockTemplate(), signatureBytes, keySet.getPublicKey(), ze.getOutputStream()); zipOutput.write(ze); if (canceled) return; // Everything else copyFiles(manifest, zioEntries, zipOutput, timestamp); if (canceled) return; } finally { zipOutput.close(); if (canceled) { try { if (outputZipFilename != null) new File(outputZipFilename).delete(); } catch (Throwable t) { getLogger().warning(t.getClass().getName() + ":" + t.getMessage()); } } } }