/**
* PEM
*
* A class to parse some PEM stuff.
* Copyright (c) 2007 Henri Torgemane
*
* See LICENSE.txt for full license information.
*/
package com.hurlant.util.der
{
import com.hurlant.crypto.rsa.RSAKey;
import com.hurlant.math.BigInteger;
import com.hurlant.util.Base64;
import flash.utils.ByteArray;
import com.hurlant.util.Hex;
public class PEM
{
private static const RSA_PRIVATE_KEY_HEADER:String = "-----BEGIN RSA PRIVATE KEY-----";
private static const RSA_PRIVATE_KEY_FOOTER:String = "-----END RSA PRIVATE KEY-----";
private static const RSA_PUBLIC_KEY_HEADER:String = "-----BEGIN PUBLIC KEY-----";
private static const RSA_PUBLIC_KEY_FOOTER:String = "-----END PUBLIC KEY-----";
private static const CERTIFICATE_HEADER:String = "-----BEGIN CERTIFICATE-----";
private static const CERTIFICATE_FOOTER:String = "-----END CERTIFICATE-----";
/**
*
* Read a structure encoded according to
* ftp://ftp.rsasecurity.com/pub/pkcs/ascii/pkcs-1v2.asc
* section 11.1.2
*
* @param str
* @return
*
*/
public static function readRSAPrivateKey(str:String):RSAKey {
var der:ByteArray = extractBinary(RSA_PRIVATE_KEY_HEADER, RSA_PRIVATE_KEY_FOOTER, str);
if (der==null) return null;
var obj:* = DER.parse(der);
if (obj is Array) {
var arr:Array = obj as Array;
// arr[0] is Version. should be 0. should be checked. shoulda woulda coulda.
return new RSAKey(
arr[1], // N
arr[2].valueOf(), // E
arr[3], // D
arr[4], // P
arr[5], // Q
arr[6], // DMP1
arr[7], // DMQ1
arr[8]); // IQMP
} else {
// dunno
return null;
}
}
/**
* Read a structure encoded according to some spec somewhere
* Also, follows some chunk from
* ftp://ftp.rsasecurity.com/pub/pkcs/ascii/pkcs-1v2.asc
* section 11.1
*
* @param str
* @return
*
*/
public static function readRSAPublicKey(str:String):RSAKey {
var der:ByteArray = extractBinary(RSA_PUBLIC_KEY_HEADER, RSA_PUBLIC_KEY_FOOTER, str);
if (der==null) return null;
var obj:* = DER.parse(der);
if (obj is Array) {
var arr:Array = obj as Array;
// arr[0] = [ <some crap that means "rsaEncryption">, null ]; ( apparently, that's an X-509 Algorithm Identifier.
if (arr[0][0].toString()!=OID.RSA_ENCRYPTION) {
return null;
}
// arr[1] is a ByteArray begging to be parsed as DER
arr[1].position = 1; // there's a 0x00 byte up front. find out why later. like, read a spec.
obj = DER.parse(arr[1]);
if (obj is Array) {
arr = obj as Array;
// arr[0] = modulus
// arr[1] = public expt.
return new RSAKey(arr[0], arr[1]);
} else {
return null;
}
} else {
// dunno
return null;
}
}
public static function readCertIntoArray(str:String):ByteArray {
var tmp:ByteArray = extractBinary(CERTIFICATE_HEADER, CERTIFICATE_FOOTER, str);
return tmp;
}
private static function extractBinary(header:String, footer:String, str:String):ByteArray {
var i:int = str.indexOf(header);
if (i==-1) return null;
i += header.length;
var j:int = str.indexOf(footer);
if (j==-1) return null;
var b64:String = str.substring(i, j);
// remove whitesapces.
b64 = b64.replace(/\s/mg, '');
// decode
return Base64.decodeToByteArray(b64);
}
}
}
|