algorithm.F5Steganography.java Source code

Java tutorial

Introduction

Here is the source code for algorithm.F5Steganography.java

Source

/*
 * This project has received funding from the European Unions Seventh 
 * Framework Programme for research, technological development and 
 * demonstration under grant agreement no FP7-601138 PERICLES.
 * 
 * Copyright 2015 Anna Eggers, State- and Univeristy Library Goettingen
 * 
 * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package algorithm;

import static main.Configuration.LIBRARY_DIRECTORY;
import static main.Configuration.RESTORED_DIRECTORY;
import static model.Criterion.CARRIER_PROCESSABILITY;
import static model.Criterion.CARRIER_RESTORABILITY;
import static model.Criterion.COMPRESSION;
import static model.Criterion.DETECTABILITY;
import static model.Criterion.ENCAPSULATION_METHOD;
import static model.Criterion.ENCRYPTION;
import static model.Criterion.PAYLOAD_ACCESSIBILITY;
import static model.Criterion.PAYLOAD_RESTORABILITY;
import static model.Criterion.STANDARDS;
import static model.Criterion.VELOCITY;
import static model.Criterion.VISIBILITY;

import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;

import org.apache.commons.io.FileUtils;
import org.apache.commons.io.filefilter.SuffixFileFilter;

import model.PayloadSegment;
import model.RestoredFile;
import model.Scenario;

/**
 * This Plug-In uses the F5 implementation from cgaffga based on Andreas Westfelds work.
 * Because of license incompatibilities the sources of F5 are delivered externally of PeriCAT. Therefore this algorithm
 * will only work if the F5.jar is present.
 */
public class F5Steganography extends AbstractAlgorithm {

    public F5Steganography() {
    }

    @Override
    Scenario defineScenario() {
        Scenario scenario = new Scenario("F5 ideal scenario");
        scenario.description = "This is the ideal scenario to use the F5 algorithm.";
        scenario.setCriterionValue(ENCAPSULATION_METHOD, EMBEDDING);
        scenario.setCriterionValue(VISIBILITY, INVISIBLE);
        scenario.setCriterionValue(DETECTABILITY, NOT_DETECTABLE);
        scenario.setCriterionValue(CARRIER_RESTORABILITY, NO);
        scenario.setCriterionValue(PAYLOAD_RESTORABILITY, YES);
        scenario.setCriterionValue(CARRIER_PROCESSABILITY, YES);
        scenario.setCriterionValue(PAYLOAD_ACCESSIBILITY, NO);
        scenario.setCriterionValue(ENCRYPTION, NO);
        scenario.setCriterionValue(COMPRESSION, YES);
        scenario.setCriterionValue(VELOCITY, YES);
        scenario.setCriterionValue(STANDARDS, NO);
        return scenario;
    }

    @Override
    SuffixFileFilter configureCarrierFileFilter() {
        List<String> supportedFileFormats = new ArrayList<String>();
        supportedFileFormats.add("jpg");
        supportedFileFormats.add("tif");
        supportedFileFormats.add("gif");
        supportedFileFormats.add("bmp");
        return new SuffixFileFilter(supportedFileFormats);
    }

    @Override
    SuffixFileFilter configurePayloadFileFilter() {
        List<String> supportedFileFormats = new ArrayList<String>();
        supportedFileFormats.add("txt");
        supportedFileFormats.add("xml");
        return new SuffixFileFilter(supportedFileFormats);
    }

    @Override
    SuffixFileFilter configureDecapsulationFileFilter() {
        return configureCarrierFileFilter();
    }

    @Override
    public File encapsulate(File carrierFile, List<File> payloadList) throws IOException {
        String carrier = getCarrier(carrierFile);
        String payload = getPayloadPathString(carrierFile, payloadList.get(0));
        String output = getOutputString(carrierFile);
        encapsulate(carrier, payload, output);
        FileUtils.forceDelete(new File(payload)); // tmp
        File outputFile = new File(output);
        if (outputFile.isFile()) {
            return outputFile;
        }
        return null;
    }

    private void encapsulate(String carrier, String payload, String output) throws IOException {
        try {
            String[] args = new String[] { "java", "-jar", LIBRARY_DIRECTORY + "f5.jar", "e", "-e", payload,
                    carrier, output };
            Process process = Runtime.getRuntime().exec(args);
            process.waitFor();
            InputStream inputStream = process.getInputStream();
            byte b[] = new byte[inputStream.available()];
            inputStream.read(b, 0, b.length);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

    private String getCarrier(File carrierFile) {
        return "" + carrierFile.toPath();
    }

    private String getPayloadPathString(File carrier, File payload) throws IOException {
        PayloadSegment payloadSegment = new PayloadSegment(carrier, payload, this);
        File payloadSemgentFile = new File("tmp");
        FileUtils.writeByteArrayToFile(payloadSemgentFile, payloadSegment.getPayloadSegmentBytes());
        return "" + payloadSemgentFile.toPath();
    }

    private String getOutputString(File carrier) {
        File outputFile = getOutputFile(carrier);
        outputFile.delete(); // F5 won't override existing files!
        return "" + outputFile.toPath();
    }

    @Override
    public List<RestoredFile> restore(File carrier) throws IOException {
        List<RestoredFile> restoredFiles = new ArrayList<RestoredFile>();
        File tmpPayload = new File("tmp");
        tmpPayload.delete(); // F5 won't override existing files!
        restore("" + tmpPayload.toPath(), "" + carrier.toPath());
        RestoredFile copiedCarrier = new RestoredFile(RESTORED_DIRECTORY + carrier.getName());
        copiedCarrier.wasCarrier = true;
        copiedCarrier.checksumValid = false;
        copiedCarrier.restorationNote = "The carrier can't be restored with this steganography algorithm. It still contains the embedded payload file(s).";
        FileUtils.copyFile(carrier, copiedCarrier);
        byte[] payloadSegmentBytes = FileUtils.readFileToByteArray(tmpPayload);
        PayloadSegment payloadSegment = PayloadSegment.getPayloadSegment(payloadSegmentBytes);
        RestoredFile restoredPayload = new RestoredFile(RESTORED_DIRECTORY + payloadSegment.getPayloadName());
        FileUtils.writeByteArrayToFile(restoredPayload, payloadSegment.getPayloadBytes());
        restoredPayload.validateChecksum(payloadSegment.getPayloadChecksum());
        restoredPayload.restorationNote = "Payload can be restored correctly.";
        restoredPayload.wasPayload = true;
        restoredPayload.originalFilePath = payloadSegment.getPayloadPath();
        copiedCarrier.originalFilePath = payloadSegment.getCarrierPath();
        restoredFiles.add(restoredPayload);
        FileUtils.forceDelete(tmpPayload);
        restoredFiles.add(copiedCarrier);// carrier can not be restored
        for (RestoredFile file : restoredFiles) {
            file.algorithm = this;
            for (RestoredFile relatedFile : restoredFiles) {
                if (file != relatedFile) {
                    file.relatedFiles.add(relatedFile);
                }
            }
        }
        return restoredFiles;
    }

    private void restore(String payload, String carrier) throws IOException {
        try {
            Process process = Runtime.getRuntime().exec(
                    new String[] { "java", "-jar", LIBRARY_DIRECTORY + "f5.jar", "x", "-e", payload, carrier });
            process.waitFor();
            InputStream inputStream = process.getInputStream();
            byte b[] = new byte[inputStream.available()];
            inputStream.read(b, 0, b.length);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

    @Override
    public String getName() {
        return "F5 Steganography";
    }

    @Override
    public String getDescription() {
        String description = "Note: The used F5 algorithm is used via an external jar f5.jar, because it is "
                + "distrubuted unter GPL v 2 license and therefore can't be included into the PeriCAT "
                + "Apache v.2 project. PeriCAT will run without the f5.jar, but then the F5 algorithm "
                + "can't be used anymore. The f5.jar has to be located in the PeriCAT_libs directory." + "\n"
                + "\nF5 is a steganography algorithm described in the paper \"F5 - A Steganography "
                + "Algorithm - High Capacity Despite Better Steganalysis - Andreas Westfeld\".\n"
                + "F5 works on image carriers of the type jpg, tif, gif, or bmp and text payload. It is "
                + "possible to restore the payload correctly in every bit, but, as typical for "
                + "steganography, the carrier can't be brought back into its original state."
                + "\nThe algorithm embedds payload images in carrier images.\n\n"
                + "https://code.google.com/p/f5-steganography/\n"
                + "f5-steganography.googlecode.com/files/F5%20Steganography.pdf\n"
                + "Abstract. Many steganographic systems are weak against visual and statistical attacks."
                + " Systems without these weaknesses offer only a relatively small capacity for "
                + "steganographic messages. The newly developed algorithm F5 withstands visual and "
                + "statistical attacks, yet it still offers a large steganographic capacity. F5 "
                + "implements matrix encoding to improve the efficiency of embedding. Thus it "
                + "reduces the number of nec- essary changes. F5 employs permutative straddling to "
                + "uniformly spread out the changes over the whole steganogram.";
        if (!new File(LIBRARY_DIRECTORY + "f5.jar").isFile()) {
            description = "WARNING: f5.jar doesn't exist.\n\n" + description;
        }
        return description;
    }

    @Override
    public boolean fulfilledTechnicalCriteria(File carrier, List<File> payloadList) {
        return carrier.isFile() && payloadList.size() == 1 && new File(LIBRARY_DIRECTORY + "f5.jar").isFile();
    }
}