Closed ghost closed 11 years ago
The error which was coming is as follows:
Error: pure virtual function call: fromDERContent
at com.hurlant.util.asn1.type::ASN1Type/fromDERContent()[/Users/timkurvers/Projects/personal/as3.crypto/src/com/hurlant/util/asn1/type/ASN1Type.as:150]
at com.hurlant.util.asn1.type::ASN1Type/fromDER()[/Users/timkurvers/Projects/personal/as3.crypto/src/com/hurlant/util/asn1/type/ASN1Type.as:131]
at com.hurlant.util.asn1.type::SequenceType/fromDERContent()[/Users/timkurvers/Projects/personal/as3.crypto/src/com/hurlant/util/asn1/type/SequenceType.as:32]
at com.hurlant.util.asn1.type::ASN1Type/fromDER()[/Users/timkurvers/Projects/personal/as3.crypto/src/com/hurlant/util/asn1/type/ASN1Type.as:131]
at com.hurlant.util.asn1.type::SequenceType/fromDERContent()[/Users/timkurvers/Projects/personal/as3.crypto/src/com/hurlant/util/asn1/type/SequenceType.as:56]
at com.hurlant.util.asn1.type::ASN1Type/fromDER()[/Users/timkurvers/Projects/personal/as3.crypto/src/com/hurlant/util/asn1/type/ASN1Type.as:131]
at com.hurlant.util.asn1.type::SequenceType/fromDERContent()[/Users/timkurvers/Projects/personal/as3.crypto/src/com/hurlant/util/asn1/type/SequenceType.as:32]
at com.hurlant.util.asn1.type::ASN1Type/fromDER()[/Users/timkurvers/Projects/personal/as3.crypto/src/com/hurlant/util/asn1/type/ASN1Type.as:131]
at com.hurlant.util.asn1.type::SequenceType/fromDERContent()[/Users/timkurvers/Projects/personal/as3.crypto/src/com/hurlant/util/asn1/type/SequenceType.as:32]
at com.hurlant.util.asn1.type::ASN1Type/fromDER()[/Users/timkurvers/Projects/personal/as3.crypto/src/com/hurlant/util/asn1/type/ASN1Type.as:131]
at com.hurlant.crypto.cert::X509Certificate/load()[/Users/timkurvers/Projects/personal/as3.crypto/src/com/hurlant/crypto/cert/X509Certificate.as:56]
at com.hurlant.crypto.cert::X509Certificate/getPublicKey()[/Users/timkurvers/Projects/personal/as3.crypto/src/com/hurlant/crypto/cert/X509Certificate.as:184]
Hi again Krish,
Thanks for the report. I'll hopefully be able to look into this shortly.
Thanks a lot Tim..I will wait for your release. Until that time, I will manage with the original library for my project work.
Also, I forgot to mention two minor things in the same test code:
1) There is some issue in isSigned(..) method of X509Certificate for verifying a 512bit RSA certificate with its Root CA certificate, where the famous unpad exception comes. This isSigned(...) method in your modified library works fine with 1024, 2048, and 4096. Not sure whether its inherited from the original library.
So, for 512bit RSA certificate verifying with its Root CA certicificate, I found that it works if you call the isSigned(..) method twice. Note in my test code line in method completeHandler() with comment "//try once more..due to some issue with 512 bit RSA certificate", where I had to call the method the second time to get 512bit RSA certificate verified. Its a cheap workaround which worked for me, but I guess there might be some issue verifying 512bit RSA certificate.
I took the 512bit Pem format RSA certificate and its Root CA from the below link, so that you can use the same. http://www.frank4dd.com/
2) I also have done a small implementation of OpenPGP (encrypting private RSA key with passphrase), by generating a hash on the passphrase using a hash algo e.g. sha256, next, using the hash generated as a Symmetric key to protect the naked private key file using a Symmetric algo e.g. aes-cbc 256 bits encryption.
Some folks were looking for this OpenPGP feature in the as3crypto library, so it might be helpful for them to refer my test code which works fine.
Also, I wrote a tiny code for verification of a RSA private key with its corresponding RSA certificate by comparing the hash of their modulus. So, this might be also a small help for guys looking for it in the library.
Thanks, Krish.
Hi Tim,
I solved the issue by debugging your modified library. Below is the modified code where the method fromDERContent was not implemented and was throwing the error. Tested the fix with some Root and Intermediate CA certificates and is working fine now. Please put the below fix.
Thanks, Krish.
package com.hurlant.util.asn1.type {
import flash.net.registerClassAlias;
import flash.utils.ByteArray;
/**
* This class represents a chunk of ASN1 definition.
*
* This is used by parser to know what to look for.
*
* @author henri
*
*/
public class ASN1Type {
registerClassAlias("com.hurlant.util.asn1.ASN1Type", ASN1Type);
// Universal types and tag numbers
public static const CHOICE:int = -2;
public static const ANY:int = -1;
public static const RESERVED:int = 0;
public static const BOOLEAN:int = 1;
public static const INTEGER:int = 2;
public static const BIT_STRING:int = 3;
public static const OCTET_STRING:int = 4;
public static const NULL:int = 5;
public static const OID:int = 6;
public static const ODT:int = 7;
public static const EXTERNAL:int = 8;
public static const REAL:int = 9;
public static const ENUMERATED:int = 10;
public static const EMBEDDED:int = 11;
public static const UTF8STRING:int = 12;
public static const ROID:int = 13;
public static const SEQUENCE:int = 16;
public static const SET:int = 17;
public static const NUMERIC_STRING:int = 18;
public static const PRINTABLE_STRING:int = 19;
public static const TELETEX_STRING:int = 20;
public static const VIDEOTEX_STRING:int = 21;
public static const IA5_STRING:int = 22;
public static const UTC_TIME:int = 23;
public static const GENERALIZED_TIME:int = 24;
public static const GRAPHIC_STRING:int = 25;
public static const VISIBLE_STRING:int = 26;
public static const GENERAL_STRING:int = 27;
public static const UNIVERSAL_STRING:int = 28;
public static const BMP_STRING:int = 30;
public static const UNSTRUCTURED_NAME:int = 31; // ??? no clue.
// Classes of tags
public static const UNIVERSAL:int = 0;
public static const APPLICATION:int = 1;
public static const CONTEXT:int = 2;
public static const PRIVATE:int = 3;
// various type modifiers
public var optional:Boolean = false;
public var implicitTag:Number = NaN;
public var implicitClass:int = 0;
public var explicitTag:Number = NaN;
public var explicitClass:int = 0;
public var defaultValue:* = null;
public var extract:Boolean = false; // if true, the constructed parent will copy the binary value in a [name]_bin slot.
// core type, vs type used somewhere
// public var core:Boolean = true;
public var defaultTag:Number;
public var parsedTag:Number; // used for ANY logic
public function ASN1Type(tag:int) {
defaultTag = tag;
}
public function matches(type:int, classValue:int, length:int):Boolean {
return false;
}
public function clone():ASN1Type {
// if (!core) {
// return this;
// }
var copier:ByteArray = new ByteArray();
// core = false; // the clone is not core
copier.writeObject(this);
copier.position = 0;
var c:ASN1Type = copier.readObject();
// if (c.core) {
// throw new Error("sucks. copy should have core=false");
// }
// core = true;
return c;
}
// ok, time to parse some shit
/**
* Read an ASN-1 value from a ByteArray and return it
* If we can't read a value that matches our type, we return null;
*
* @param s a ByteArray containing some DER-encoded ASN-1 values.
* @return an ASN1Value object representing the value read. or null.
*
*/
public function fromDER(s:ByteArray, size:int):* {
var p:int = s.position; // We'll reset if things go wrong.
var length:int;
aleg: do {
if (!isNaN(explicitTag)) {
// unwrap the explicit tag..
var tag:int = readDERTag(s, explicitClass, true); // explicit tags are always constructed
if (tag!=explicitTag) {
break aleg; // haha! The wit.
}
length = readDERLength(s);
// XXX I should use length to validate stuff.
}
if (!isNaN(implicitTag)) {
tag = readDERTag(s, implicitClass);
if (tag!=implicitTag) {
break aleg;
}
} else {
tag = readDERTag(s);
if (defaultTag == ANY) {
parsedTag = tag;
} else if (tag!=defaultTag) {
break aleg;
}
}
length = readDERLength(s);
var c:* = fromDERContent(s, length);
if (c==null) {
break aleg;
}
return c;
} while(false);
// we failed to parse something meaningful. fall back.
s.position = p;
if (defaultValue!=null) {
return fromDefaultValue();
}
return null;
}
protected function fromDefaultValue():* {
return defaultValue;
}
protected function fromDERContent(s:ByteArray, length:int):* {
return s.readBoolean();
//throw new Error("pure virtual function call: fromDERContent");
}
protected function readDERTag(s:ByteArray, classValue:int=UNIVERSAL,
constructed:Boolean=false, any:Boolean=false):int {
var type:int = s.readUnsignedByte();
var c:Boolean = (type&0x20)!=0;
var cv:int = (type&0xC0)>>6; // { universal, application, context, private }
type &= 0x1F;
if (type == 0x1F) {
// multibyte tag. blah.
type=0;
do {
var o:int = s.readUnsignedByte();
var v:int = o&0x7F;
type = (type<<7) + v;
} while (o&0x80!=0);
}
if (classValue!=cv) {
// trace("Tag Class Mismatch. expected "+classValue+", found "+cv);
//return -1; // tag class mismatch // XXX ignore that for now.. :(
}
return type;
// checking for "constructed" is a bit tedious. skip for now. XXX
//if (any || (c==constructed)) return type;
//return -1; // constructed flag mismatch.
}
protected function readDERLength(s:ByteArray):int {
// length
var len:int = s.readUnsignedByte();
if (len>=0x80) {
// long form of length
var count:int = len & 0x7f;
len = 0;
while (count>0) {
len = (len<<8) | s.readUnsignedByte();
count--;
}
}
return len;
}
}
}
Hi again,
Thanks for looking into this issue a bit more thoroughly, appreciated!
I'm starting to think the original SWC is not in sync with the latest original source code (see line 149), which would explain this. Could you link me to or confirm the original project and SWC you used?
I am very close to being able to look into these ActionScript projects again, still meddling with my development environment.
Hi Tim,
Actually, first I was using your SWC, then due to the error, I reverted to the original SWC and that error went away. I also checked the latest SVN code of the original project, but could not understand why the fix is missing there. Also the zip package available for download in the original project has many things missing in the "util" folder, only one can view those in the svn in browse mode. So, I never used the original project, but only used its SWC.
But yesterday, I again deleted the original SWC from my project and I download your latest project source code (since I wanted to use some of the Type2.as things you have written and made some public getter methods to read certificate information the way keystore shows it). So, when I started getting the error again, I could now debug to find out where the error in coming e.g. line 149 and I pasted the missing line over there and it started working for all my test certificates.
Thanks, Krish.
Hi Tim,
I was using your modified .swc and it was working fine for my Hybrid Crypto project which I am attempting to integrate as3crypto library with SAP, untill I found an error which is causing problem with most Root CA or Intermediate CA certificates while getting public key. The full error text is attached.
I resolved this issue by reverting to the original Henri's version swc, which was also working fine for my use cases, but had used your swc instead earlier thinking it was an updated version.
In another post, I found out the solution in the below which some people has adopted who was getting the same error.
http://code.google.com/p/as3crypto/issues/detail?id=25
Being a non-Flex person, I guess that this fix is already part of the original swc and some line might be broken or missing in your modified version. Please let me know when you have fixed this issue and released the latest swc so that I can download your version.
Thanks, Krish.
My test code for uploading certificate which you can run using flash player 10 minimum to replicate the problem while trying to upload Root CA from the list mentioned.