Generating Chrome Packaged App .crx header with Java - google-app-engine

I"m trying to build the header in Java with no luck.
(here is the spec: https://developer.chrome.com/extensions/crx)
Any ideas?
protected void geneateCrxHeader (OutputStream ins,byte[] zipArchive) throws NoSuchAlgorithmException, NoSuchProviderException, IOException, InvalidKeyException, SignatureException{
KeyPairGenerator keyGen = KeyPairGenerator.getInstance("RSA");
SecureRandom random = SecureRandom.getInstance("SHA1PRNG", "SUN");
keyGen.initialize(1024, random);
KeyPair pair = keyGen.generateKeyPair();
byte[] key = pair.getPublic().getEncoded();
Signature instance = Signature.getInstance("SHA1withRSA");
instance.initSign(pair.getPrivate());
instance.update(zipArchive);
byte[] hash = instance.sign();
byte[] magic = {0x43,0x72,0x32,0x34,0x02,0x00,0x00,0x00,0x00,0x01,0x0E,0x0B,0x00,0x00,0x08,0x00};
ins.write(magic);
ins.write(key);
ins.write(hash);
}
and I get CRX_EXCESSIVELY_LARGE_KEY_OR_SIGNATURE..
I must be using wrong keygen.
in the docs they do say :
"..the contents of the author's RSA public key, formatted as an X509 SubjectPublicKeyInfo block. .."
i wonder if that is what i'm not doing correctly...
p.s Java crypto is a new frontier for me , so pls don't laugh if I did something totally dumb.

Here is some code that I whipped up and didn't test that illustrates producing just the header. I based this solely on reading the spec.
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.SecureRandom;
import java.security.Signature;
public static byte[] generateCrxHeader(byte[] extensionContents) throws Exception {
KeyPairGenerator keyGen = KeyPairGenerator.getInstance("RSA");
SecureRandom random = new SecureRandom();
keyGen.initialize(1024, random);
KeyPair pair = keyGen.generateKeyPair();
Signature sigInstance = Signature.getInstance("SHA1withRSA");
sigInstance.initSign(pair.getPrivate());
sigInstance.update(extensionContents);
byte [] signature = sigInstance.sign();
byte [] subjectPublicKeyInfo = pair.getPublic().getEncoded();
final int headerLength = 4 + 4 + 4 + 4 + subjectPublicKeyInfo.length + signature.length;
ByteBuffer headerBuf = ByteBuffer.allocate(headerLength);
headerBuf.order(ByteOrder.LITTLE_ENDIAN);
headerBuf.put(new byte[]{0x43,0x72,0x32,0x34}); // Magic number
headerBuf.putInt(2); // Version
headerBuf.putInt(subjectPublicKeyInfo.length); // public key length
headerBuf.putInt(signature.length); // signature length
headerBuf.put(subjectPublicKeyInfo);
headerBuf.put(signature);
final byte [] header = headerBuf.array();
return header;
}

Related

Check if SSH Private Key is Encrypted

Key pairs generated with ssh-keygen on macOS can have different formats.
The standard PEM ASN.1 object which is readable by macOS' SecKey APIs
A PEM with textual headers
OpenSSH Keys
OpenSSH Encrypted Keys
OpenSSH/BSD uses this non-standardized format here.
Now I only need to be able to check if a private key has a passphrase set or not, so I can prompt the user to enter it, without having to deal with the complexities of different key formats.
Is there a quick way on macOS via Swift or C API, to check if a key has a passphrase set?
The difference between the unencrypted and encrypted private keys is the fact that the key blob is encrypted. You need to decrypt the private key blob data before you can use the private key blob. So once the encrypted private key data is decoded, you can treat it the same as the unencrypted private key data.
A unencrypted private key blob PEM file looks like this:
—–BEGIN PRIVATE KEY—–
{base64 private key blob)
—–END PRIVATE KEY—–
The encrypted RSA private key PEM file looks like this:
—–BEGIN RSA PRIVATE KEY—–
Proc-Type: 4,ENCRYPTED
DEK-Info: {encryption algorithm},{salt}
{base64 encrypted private key blob)
—–END RSA PRIVATE KEY—–
e.g.
—–BEGIN RSA PRIVATE KEY—–
Proc-Type: 4,ENCRYPTED
DEK-Info: AES-256-CBC,AB8E2B5B2D989271273F6730B6F9C687
{base64 encrypted private key blob)
—–END RSA PRIVATE KEY—–
So to decode the private key data you need to:
Parse the DEK-Info encryption algorithm and the salt (good idea to confirm the first line is: "Proc-Type: 4,ENCRYPTED" as well).
Decode the base64 encrypted private key blob.
Generate the encryption algorithm "key" and "IV" based on the salt and the passphrase
Decode the encrypted private key blob.
Once you have done that the decrypted private key blob can be treated just like the unencoded private key blob.
The number of supported encryption algorithm's are rather large, so you may like to support a sub-set of algorithms. e.g. "DES-EDE3-CBC", "AES-xxx-CBC", etc
To generate the IV you need to convert salt string to binary. The salt string is a hex encoded string, so convert each two strings characters into a byte using a hex string character to byte converter.
For the generation of the encryption algorithm key you need the key size (e.g. DES-EDE3-CBC is 192bits, AES-256-CBC is 256bits). Build up the key "bits" with a loop appending MD5 hash results to the key until generate all the key bits required.
The MD5 HASH loop generation will consist of:
First MD5 Hash: MD5 hash of the first 8 bytes of the IV and the Passphrase
All other MD5 Hashes is the MD5 hash of the last MD5 hash result and the first 8 bytes of the IV and the Passphrase
See the openssl source for EVP_BytesToKey method for an example of the key bits generation.
The encrypted private key blob can now be decoded using the selected encryption algorithm using the IV and KEY build above.
There are two ways that I would suggest. Either reading the command line output using readLine() and checking if it asks for a password then do something accordingly.
import Foundation
func runCommand(cmd : String, args : String...) -> (output: [String], error: [String], exitCode: Int32) {
var output : [String] = []
var error : [String] = []
let task = Process()
task.launchPath = cmd
task.arguments = args
let outpipe = Pipe()
task.standardOutput = outpipe
let errpipe = Pipe()
task.standardError = errpipe
task.launch()
let outdata = outpipe.fileHandleForReading.readDataToEndOfFile()
if var string = String(data: outdata, encoding: .utf8) {
string = string.trimmingCharacters(in: .newlines)
output = string.components(separatedBy: "\n")
}
let errdata = errpipe.fileHandleForReading.readDataToEndOfFile()
if var string = String(data: errdata, encoding: .utf8) {
string = string.trimmingCharacters(in: .newlines)
error = string.components(separatedBy: "\n")
}
task.waitUntilExit()
let status = task.terminationStatus
return (output, error, status)
}
//Sample usage
let (output, error, status) = runCommand(cmd: "/usr/local/bin/node", args: "--version")
print("program exited with status \(status)")
if output.count > 0 {
print("program output:")
print(output)
//HERE YOU CAN CHECK IF PASSWORD REQUEST HAS BEEN MADE
}
if error.count > 0 {
print("error output:")
print(error)
}
The example code will return your node version installed if there is one, but you could use it to check if a password prompt has been made by the system for the RSA Key.
The other way could be perhaps using a third-party library like SwiftyRSA or BlueRSA which might help with validation.
I implemented my own OpenSSH check for the 2 most common formats
For one I'm checking the PEM headers for DEK-Info for Linux-style SSH PEMs
For OpenSSH style keys I manually parse the format using the class below
import Foundation
private let opensshMagic = "openssh-key-v1"
public class SSHPrivateKey {
public struct OpenSSHKey {
let cipherName: String
let kdfName: String
let kdfOptions: Data
let numKeys: Int
var isEncrypted: Bool {
return cipherName != "none"
}
}
public let data: Data
public init(data: Data) {
self.data = data
}
public func openSSHKey() -> OpenSSHKey? {
// #define AUTH_MAGIC "openssh-key-v1"
//
// byte[] AUTH_MAGIC
// string ciphername
// string kdfname
// string kdfoptions
// int number of keys N
// string publickey1
// string publickey2
// ...
// string publickeyN
// string encrypted, padded list of private keys
guard let magic = opensshMagic.data(using: .utf8) else {
return nil
}
if data.prefix(magic.count) != magic {
return nil
}
var offset = magic.count + 1
guard let cipherName = data.consumeString(offset: &offset),
let kdfName = data.consumeString(offset: &offset) else {
return nil
}
let kdfOptions = data.consumeBytes(offset: &offset)
let numKeys = data.consumeUInt32(offset: &offset)
return OpenSSHKey(cipherName: cipherName,
kdfName: kdfName,
kdfOptions: kdfOptions,
numKeys: Int(numKeys))
}
}
private extension Data {
func consumeBytes(offset: inout Int) -> Data {
let n = Int(consumeUInt32(offset: &offset))
let b = Data(self[offset..<offset + n])
offset += n
return b
}
func consumeString(offset: inout Int) -> String? {
return consumeBytes(offset: &offset).utf8String
}
func consumeUInt8(offset: inout Int) -> UInt8 {
let v = self[offset] & 0xFF
offset += 1
return v
}
func consumeUInt32(offset: inout Int) -> UInt32 {
var i: UInt32 = 0
i = (i << 8) | UInt32(consumeUInt8(offset: &offset))
i = (i << 8) | UInt32(consumeUInt8(offset: &offset))
i = (i << 8) | UInt32(consumeUInt8(offset: &offset))
i = (i << 8) | UInt32(consumeUInt8(offset: &offset))
return i
}
}

Building a String array from a text file without collection classes

I am trying to build an array from a buffered in text file. This class is used by another class with a main method. What I have only prints the file... what I need is to have an array of strings, built line by line, mirroring the text file. I need to be able to then search against that array using a String from user input (that part will be in main method too) that will name a product, and find the corresponding price. I can't use things like ArrayList, Maps, Vectors, etc. This is in Java8.
/**
* A class that reads in inventory from vmMix1 text file using BufferedReader
* # author Michelle Merritt
*/
import java.io.*;
public class VendingMachine1
{
BufferedReader inInvFile1 = new BufferedReader(
new FileReader("vmMix1.txt"))
/**
* A method to print vending machine 1 inventory
*/
public void printVM1()
{
try
{
String vm1Line;
while((vm1Line = inInvFile1.readLine()) != null)
{
// This is what I was using for now to simply print my file
System.out.println(vm1Line);
}
}
catch(IOException e)
{
System.out.println("I/O Error: " + e);
}
}
}
This is the code that created my text file, since I can't seem to see how I attach the text file instead.
/**
* A class that creates the inventory found in vending machine #1, using
* a PrintWriter stream.
* # author Michelle Merritt
*/
import java.io.*;
public class VMMix1
{
public static void main(String[] args)
{
String [] product = {"Coke", "Dr. Pepper", "Sprite", "RedBull",
"Cool Ranch Doritos", "Lay's Potato Chips",
"Pretzels", "Almonds", "Snickers", "Gummi Bears",
"Milky Way", "KitKat"};
String [] packaging = {"bottle", "can", "can", "can", "bag", "bag",
"bag", "bag", "wrapper", "bag", "wrapper",
"wrapper"};
float [] price = {2.25f, 1.75f, 1.75f, 2.00f, 1.00f, 1.00f, 0.75f, 1.50f,
1.25f, 1.00f, 1.25f, 1.25f};
int [] quantity = {10, 10, 10, 12, 8, 10, 12, 9, 7, 11, 10, 8};
try(PrintWriter outFile = new PrintWriter("vmMix1.txt"))
{
for (int index = 0; index < product.length; index++)
{
outFile.printf("%-18s %-10s: $%.2f qty: %3d\n", product[index],
packaging[index], price[index], quantity[index]);
}
}
catch (IOException except)
{
System.out.println("IOException: " + except.getMessage());
}
}
}
I need for this thing to be dynamic. As the program runs, and something is purchased, I will have to account for losing inventory and changing the amount of money in the vending machine (there's another class for currency that houses quantities of denominations of money). I have to maintain the values in the array and reprint the updated array. Any help is much appreciated.
You may use Java8 stream API
String[] array = reader.lines().toArray(String[]::new);
You could even skip the buffer creation using
try (Stream<String> stream = Files.lines(Paths.get("vmMix1.txt"))) {
String [] array = stream.toArray(String[]::new);
}
Pre-Java8, probably one of the shortest way is to read the entire file into a string, and split it (ways to read a reader into string can be found here):
String[] array = fileAsString.split('\\n');
Of course you could also built the array in your loop and increase it for every line using System.arraycopy (which can be quite slow in that case).
String[] array = new String[0];
while((vm1Line = inInvFile1.readLine()) != null) {
String[] newArray = new String[array.length + 1];
System.arraycopy(array, 0, newArray, 0, array.length);
newArray[array.length] = vm1Line;
array = newArray;
}
You may optimize this approach by creating a larger array first, fill in the lines, increase size of the array as needed (using arraycopy), and finally shrink the array to the number of written lines.
Thats more or less what an array list does. So in case you may use the collections api, you could simply do
List<String> list = new ArrayList<>();
while((vm1Line = inInvFile1.readLine()) != null) {
list.add(vm1Line);
}
String[] array = list.toArray(new String[list.size()]);
Hope it helps.
Stream<String> lines = Files.lines(Paths.get("C:/SelfStudy/Input.txt"));
String[] array = lines.toArray(String[]::new);

How do I run an encryption program multiple times to strengthen the encode?

Here is my code so far. I need to run the encode part of the code 5 times and then decode the encode the same number of times. I figured out how to encode the message but now I can't figure out how to run the "encode" or "decode" variable back through the code to strengthen the ecryption.
public class Codes
{
/**
* Encode and decode a message using a key of values stored in
* a queue.
*/
public static void main(String[] args)
{
int[] key = {7, 6, 5, 2, 8, 5, 8, 6, 4, 1};
Integer keyValue;
String encoded = "", decoded = "";
String message = "Queues are useful for encoding messages.";
Queue<Integer> encodingQueue = new LinkedList<Integer>();
Queue<Integer> decodingQueue = new LinkedList<Integer>();
// load key queues
for (int scan = 0; scan < key.length; scan++)
{
encodingQueue.add(key[scan]);
decodingQueue.add(key[scan]);
}
// encode message
for (int scan = 0; scan < message.length(); scan++)
{
keyValue = encodingQueue.remove();
encoded += (char) (message.charAt(scan) + keyValue);
encodingQueue.add(keyValue);
}
System.out.println ("Encoded Message:\n" + encoded + "\n");
// decode message
for (int scan = 0; scan < encoded.length(); scan++)
{
keyValue = decodingQueue.remove();
decoded += (char) (encoded.charAt(scan) - keyValue);
decodingQueue.add(keyValue);
}
System.out.println ("Decoded Message:\n" + decoded);
}
}
as of right now I am receiving this output:
Encoded Message:
X{jwmx(gvf'{xgnzt&jpy&jpktlorh'sju{fokw/
Decoded Message:
Queues are useful for encoding messages.
In order to complete this program I need the output to look like this:
Encoded Message 1: X{jwmx(gvf'{xgnzt&jpy&jpktlorh'sju{fokw/
Encoded Message 2: _?oyu}0mzg.?}iv•|,nq?,orsytuvi.yow?kwq{0
Encoded Message 3: f?t{}?8s~h5??k~??2rr?2tt{~|{zj5•ty?p•w•1
Encoded Message 4: m?y}??#y?i<??m???8vs?8yv????~k<?y{?u?}?2
Encoded Message 5: t?~•??H•?jC??o???>zt?>~x?????lC?~}?z???3
Decoded Message 5: m?y}??#y?i<??m???8vs?8yv????~k<?y{?u?}?2
Decoded Message 4: f?t{}?8s~h5??k~??2rr?2tt{~|{zj5•ty?p•w•1
Decoded Message 3: _?oyu}0mzg.?}iv•|,nq?,orsytuvi.yow?kwq{0
Decoded Message 2: X{jwmx(gvf'{xgnzt&jpy&jpktlorh'sju{fokw/
Decoded Message 1: Queues are useful for encoding messages.
I estimate that in order to make this happen I need to use a loop to run the "encode" and "decode" variables back through the program. However I cannot figure out how to make that happen.
This will be easier if you use separate functions for the encode() and decode() operations:
class Codes {
public static void main(String[] args) {
...
}
private static String encode(String plaintext, Queue<Integer> encodingQueue) {
...
}
private static String decode(String ciphertext, Queue<Integer> decodingQueue) {
...
}
}
Does that help?

converting java to perl (md5)

I am trying converting java to perl (md5)program.
How can i do following two programs same output MD5 sum.
Java
import java.security.MessageDigest;
import java.math.BigInteger;
public class Hash
{
public static void main( String[] args ) throws Exception
{
MessageDigest md5 = MessageDigest.getInstance("MD5");
String plain = "abcd1234";
BigInteger digest = new BigInteger(md5.digest(plain.getBytes("UTF-8")));
System.out.println( digest.abs() );
}
}
Perl
use Digest::MD5 'md5_hex';
use Math::BigInt;
my $plain = "abcd1234";
my $digest = Math::BigInt::->from_hex(md5_hex $plain);
print $digest, "\n";
I Think,
Java:
BigInteger digest = new BigInteger(md5.digest(plain.getBytes("UTF-8")));
Perl:
my $digest = Math::BigInt::->from_hex(md5_hex $plain);
here is diffrent output MD5 sum.
I want to edit perl source.
Your BigInteger() call requires a byte array containing the two's complement binary representation of the number. You need to use the sign-magnitude constructor:
public BigInteger(int signum, byte[] magnitude)
So, your Java code should be:
import java.security.MessageDigest;
import java.math.BigInteger;
public class Hash
{
public static void main(String[] args) throws Exception
{
MessageDigest md5 = MessageDigest.getInstance("MD5");
String plain = "abcd1234";
BigInteger digest = new BigInteger(1, md5.digest(plain.getBytes("UTF-8")));
System.out.println(digest.abs());
}
}
Your Perl code didn't quite work for me, either. My version of Math::BigInt requires a string representation of the hex value, like so:
use Digest::MD5 'md5_hex';
use Math::BigInt;
my $plain = "abcd1234";
my $digest = Math::BigInt::->from_hex('0x' . md5_hex($plain));
print $digest, "\n";
When I run those two commands, I get the same digest value displayed.

How to split a File Source into Strings or Words

I have a file with content like this:
"Some","Words","separated","by","comma","and","quoted","with","double","quotes"
The File is to large to read it into just on String.
What is the simplest way to split it into a Traversable of Strings, with each element being a word?
If it matters: While the content of the file won't fit in a single String the resulting Traversable might be a List without a problem.
Here is an adaptation of your own solution, using JavaConversions to manipulate the Java iterator as a Scala one.
import java.util.Scanner
import java.io.File
import scala.collection.JavaConversions._
val scanner = new Scanner(new File("...")).useDelimiter(",")
scanner.map(_.trim).map(quoted => quoted.substring(1, quoted.length - 1))
This gives you an iterator. You can always convert it to a list using e.g. .toList.
Here is a version using stringLit and repsep from Scala parser combinators. I won't vouch for its efficiency, though.
import scala.util.parsing.combinator.syntactical.StdTokenParsers
import scala.util.parsing.combinator.lexical.StdLexical
import scala.util.parsing.input.StreamReader
import java.io.FileReader
object P extends StdTokenParsers {
type Tokens = StdLexical
val lexical = new StdLexical
lexical.delimiters += ","
def words : Parser[List[String]] = repsep(stringLit, ",")
def getWords(fileName : String) : List[String] = {
val scanner = new lexical.Scanner(StreamReader(new FileReader(fileName)))
// better error handling wouldn't hurt.
words(scanner).get
}
}
I did it using the java.util.Scanner while it does work, I'd appreciate a more scalaesc version.
val scanner = new Scanner(new File("""bigFile.txt""")).useDelimiter(",")
var wordList: Vector[String] = Vector()
while (scanner.hasNext()) {
val quoted = scanner.next()
val word = quoted.replace("\"", "")
wordList = wordList :+ word
}

Resources