blob: 8bd71927c05a0767ae8086d471a072b3d7e69a1e [file] [log] [blame]
/*
* Copyright (c) 2020 Kentyou.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Kentyou - initial API and implementation
*/
package org.eclipse.sensinact.gateway.security.signature.internal;
import org.eclipse.sensinact.gateway.common.bundle.Mediator;
import org.eclipse.sensinact.gateway.util.IOUtils;
import java.io.BufferedReader;
import java.io.ByteArrayInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.security.NoSuchAlgorithmException;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.jar.Attributes;
public class ManifestChecker {
private ManifestChecker() {
// no action
}
public static byte[] getNextSection(final byte[] fileData, final int offset) {
// final Logger logger = Logger.getLogger(LoggerConfig.JARVAL_LOGGER);
final int nextSectionLength = ManifestChecker.getNextSectionLength(fileData, offset);
// logger.log(Level.ALL, "section length: "+nextSectionLength);
final byte[] newSectionData = new byte[nextSectionLength];
if (nextSectionLength != 0) {
System.arraycopy(fileData, offset, newSectionData, 0, nextSectionLength);
}
return newSectionData;
}
private static int getNextSectionLength(final byte[] rawManifestData, final int offset) {
int startOfNext = 0;
int length = 0;
boolean found = false;
if (rawManifestData != null) {
int j = offset;
final int k = rawManifestData.length;
boolean flag = true;
byte byte0;
for (; j < k && !found; j++) {
byte0 = rawManifestData[j];
//final byte[] array = { byte0 };
switch (byte0) {
case 13: // '\r'
if (j < k && rawManifestData[j + 1] == 10) {
j++;
}
if (flag || j == k - 1) {
startOfNext = j + 1;
found = true;
length = startOfNext - offset;
}
flag = true;
break;
case 10: // '\n'
if (flag || j == k - 1) {
startOfNext = j + 1;
found = true;
length = startOfNext - offset;
}
flag = true;
break;
default:
flag = false;
break;
}
}
}
if (!found) {
length = startOfNext - offset;
}
// to check
if (length < 0) {
length = 0;
}
return length;
}
public static Map<String, String> extractEntryHashes(Mediator mediator, InputStream iStream, CryptographicUtils cryptoUtils, String hashAlgo) throws FileNotFoundException, IOException, NoSuchAlgorithmException {
final Map<String, String> dataMap = new HashMap<String, String>();
final byte[] fileData = IOUtils.read(iStream);
String shaDigestType = null;
String shaDigestMfMain = null;
if ("SHA-1".equals(hashAlgo)) {
shaDigestType = "SHA1-Digest";
shaDigestMfMain = "SHA1-Digest-Manifest-Main-Attributes";
} else if ("SHA-256".equals(hashAlgo)) {
shaDigestType = "SHA-256-Digest";
shaDigestMfMain = "SHA-256-Digest-Manifest-Main-Attributes";
} else {
//let's try
shaDigestType = hashAlgo + "-Digest";
shaDigestMfMain = hashAlgo + "-Digest-Manifest-Main-Attributes";
}
// get main attributes
final byte[] mfMainAttributes = SignedBundleManifest.getManifestMainAttributesAsBytes(fileData);
final String mfMainAttributesHash = cryptoUtils.getHashValue(mfMainAttributes, shaDigestType);
dataMap.put(shaDigestMfMain, mfMainAttributesHash);
// for all entries
// get entry
byte[] currentEntryData;
String entryName, entryHash;
int offset = mfMainAttributes.length;
while ((currentEntryData = ManifestChecker.getNextSection(fileData, offset)) != null && currentEntryData.length > 0) {
entryName = ManifestChecker.getEntryName(currentEntryData);
entryHash = cryptoUtils.getHashValue(currentEntryData, shaDigestType);
dataMap.put(entryName, entryHash);
offset += currentEntryData.length;
}
return dataMap;
}
protected static String getEntryHash(final Attributes atts) {
String entryHash = "";
if (atts != null) {
final Iterator iter = atts.entrySet().iterator();
if (iter.hasNext()) {
entryHash = (String) ((Map.Entry) iter.next()).getValue();
}
}
return entryHash;
}
private static String getEntryName(byte[] currentEntryData) throws IOException {
String entryName = "", nameHeader = "Name: ", line;
BufferedReader bReader = null;
try {
bReader = new BufferedReader(new InputStreamReader(removeShortLines(new ByteArrayInputStream(currentEntryData))));
boolean nameFound = false;
while (!nameFound && (line = bReader.readLine()) != null) {
if (line.startsWith(nameHeader)) {
entryName = line.substring(nameHeader.length());
nameFound = true;
}
}
} finally {
if (bReader != null) {
try {
bReader.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
return entryName;
}
public static InputStream removeShortLines(InputStream iStream) throws IOException {
BufferedReader bReader = new BufferedReader(new InputStreamReader(iStream));
String line;
int shortlineLength = 70;
StringBuffer longLineData = new StringBuffer();
;
while ((line = bReader.readLine()) != null) {
longLineData = addLine(bReader, longLineData, line, shortlineLength);
}
return new ByteArrayInputStream(longLineData.toString().getBytes());
}
public static StringBuffer addLine(final BufferedReader bReader, final StringBuffer longLineData, final String line, final int shortlineLength) throws IOException {
String currentLine = line;
if (currentLine != null) {
if (currentLine.length() < shortlineLength) {
longLineData.append(currentLine).append("\r\n");
} else if (currentLine.length() == shortlineLength) {
longLineData.append(currentLine);
while ((currentLine = bReader.readLine()).startsWith(" ")) {
longLineData.append(currentLine.substring(1));
}
longLineData.append("\r\n");
addLine(bReader, longLineData, currentLine, shortlineLength);
}
}
return longLineData;
}
}