108 lines
3.2 KiB
ActionScript
108 lines
3.2 KiB
ActionScript
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;
|
|
|
|
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 OID_RSA_ENCRYPTION:String = "1.2.840.113549.1.1.1";
|
|
|
|
/**
|
|
*
|
|
* 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 {
|
|
// 1. we expect a "-----BEGIN RSA PRIVATE KEY-----"
|
|
var i:int = str.indexOf(RSA_PRIVATE_KEY_HEADER);
|
|
if (i==-1) return null;
|
|
i += RSA_PRIVATE_KEY_HEADER.length;
|
|
var j:int = str.indexOf(RSA_PRIVATE_KEY_FOOTER);
|
|
if (j==-1) return null;
|
|
var b64:String = str.substring(i, j);
|
|
// remove any whitespace characters from the string
|
|
var space:RegExp= /\s/mg;
|
|
b64 = b64.replace(space,'');
|
|
// decode
|
|
var der:ByteArray = Base64.decodeToByteArray(b64);
|
|
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 i:int = str.indexOf(RSA_PUBLIC_KEY_HEADER);
|
|
if (i==-1) return null;
|
|
i += RSA_PUBLIC_KEY_HEADER.length;
|
|
var j:int = str.indexOf(RSA_PUBLIC_KEY_FOOTER);
|
|
if (j==-1) return null;
|
|
var b64:String = str.substring(i, j);
|
|
// remove whitesapces.
|
|
b64 = b64.replace(/\s/mg, '');
|
|
// decode
|
|
var der:ByteArray = Base64.decodeToByteArray(b64);
|
|
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;
|
|
}
|
|
}
|
|
|
|
}
|
|
} |