All Downloads are FREE. Search and download functionalities are using the official Maven repository.

net.neoforged.art.internal.SignatureStripperTransformer Maven / Gradle / Ivy

There is a newer version: 2.0.5
Show newest version
/*
 * Copyright (c) Forge Development LLC and contributors
 * SPDX-License-Identifier: LGPL-2.1-only
 */

package net.neoforged.art.internal;

import net.neoforged.art.api.SignatureStripperConfig;
import net.neoforged.art.api.Transformer;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.util.Iterator;
import java.util.Locale;
import java.util.Map;
import java.util.function.Consumer;
import java.util.jar.Attributes;
import java.util.jar.Manifest;

public class SignatureStripperTransformer implements Transformer {
    private final Consumer log;
    private final SignatureStripperConfig config;

    public SignatureStripperTransformer(Consumer log, SignatureStripperConfig config) {
        this.log = log;
        this.config = config;
    }

    @Override
    public ManifestEntry process(ManifestEntry entry) {
        // Remove all signature entries
        // see signed jar spec: https://docs.oracle.com/javase/7/docs/technotes/guides/jar/jar.html#Signed_JAR_File
        try {
            final Manifest manifest = new Manifest(new ByteArrayInputStream(entry.getData()));
            boolean found = false;
            for (final Iterator> it = manifest.getEntries().entrySet().iterator(); it.hasNext();) {
                final Map.Entry section = it.next();
                for (final Iterator> attrIter = section.getValue().entrySet().iterator(); attrIter.hasNext();) {
                    final Map.Entry attribute = attrIter.next();
                    final String key = attribute.getKey().toString().toLowerCase(Locale.ROOT); // spec says this is case-insensitive
                    if (key.endsWith("-digest")) { // assume that this is a signature entry
                        if (this.config == SignatureStripperConfig.ALL) {
                            attrIter.remove();
                        }
                        found = true;
                    }
                    // keep going even if we've found an attribute -- multiple hash formats can be specified for each file
                }

                if (section.getValue().isEmpty()) {
                    it.remove();
                }
            }
            if (found) {
                try (final ByteArrayOutputStream os = new ByteArrayOutputStream()) {
                    manifest.write(os);
                    return ManifestEntry.create(entry.getTime(), os.toByteArray());
                }
            }
        } catch (final IOException ex) {
            log.accept("Failed to remove signature entries from manifest: " + ex);
        }
        return entry;
    }

    @Override
    public ResourceEntry process(ResourceEntry entry) {
        // Signature metadata
        if (entry.getName().startsWith("META-INF/")) {
            if (entry.getName().endsWith(".RSA")
                    || entry.getName().endsWith(".SF")
                    || entry.getName().endsWith(".DSA")
                    || entry.getName().endsWith(".EC")) { // supported by InstallerRewriter but not referenced in the spec
                return null;
            }
        }
        return entry;
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy