[caffeine-hx] r659 committed - x509 openssl modifications...

0 views
Skip to first unread message

caffe...@googlecode.com

unread,
Feb 20, 2012, 1:14:45 PM2/20/12
to caffein...@googlegroups.com
Revision: 659
Author: damon...@gmail.com
Date: Mon Feb 20 10:13:32 2012
Log: x509 openssl modifications
Moving RSA into its own package


http://code.google.com/p/caffeine-hx/source/detail?r=659

Added:
/trunk/ext3/chx/crypt/rsa
/trunk/ext3/chx/crypt/rsa/IBlockPad.hx
/trunk/ext3/chx/crypt/rsa/PadBlockBase.hx
/trunk/ext3/chx/crypt/rsa/PadPkcs1Type1.hx
/trunk/ext3/chx/crypt/rsa/PadPkcs1Type2.hx
/trunk/ext3/chx/crypt/rsa/RSA.hx
/trunk/ext3/chx/crypt/rsa/RSAEncrypt.hx
Deleted:
/trunk/ext3/chx/crypt/IBlockPad.hx
/trunk/ext3/chx/crypt/PadBlockBase.hx
/trunk/ext3/chx/crypt/PadPkcs1Type1.hx
/trunk/ext3/chx/crypt/PadPkcs1Type2.hx
/trunk/ext3/chx/crypt/RSA.hx
/trunk/ext3/chx/crypt/RSAEncrypt.hx
Modified:
/trunk/ext3/chx/crypt/cert/X509Certificate.hx

=======================================
--- /dev/null
+++ /trunk/ext3/chx/crypt/rsa/IBlockPad.hx Mon Feb 20 10:13:32 2012
@@ -0,0 +1,50 @@
+/*
+ * Copyright (c) 2012, The Caffeine-hx project contributors
+ * Original author : Russell Weir
+ * Contributors:
+ * All rights reserved.
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE CAFFEINE-HX PROJECT CONTRIBUTORS "AS
IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE CAFFEINE-HX PROJECT CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+package chx.crypt;
+
+interface IBlockPad {
+ /** finished padded block size **/
+ var blockSize(default,setBlockSize) : Int;
+
+ function pad( s : Bytes ) : Bytes;
+
+ function unpad( s : Bytes ) : Bytes;
+
+ /** returns the number of blocks for message length len **/
+ function calcNumBlocks(len : Int) : Int;
+
+ /** number of bytes padding needs per block **/
+ function blockOverhead() : Int;
+
+ /**
+ * Number of bytes of source material that will actually be written into
each block.
+ * On block pads, this will be less than the block size.
(blockSize-blockOverhead)
+ **/
+ function getBytesReadPerBlock() : Int;
+
+}
=======================================
--- /dev/null
+++ /trunk/ext3/chx/crypt/rsa/PadBlockBase.hx Mon Feb 20 10:13:32 2012
@@ -0,0 +1,57 @@
+/*
+ * Copyright (c) 2011, The Caffeine-hx project contributors
+ * Original author : Russell Weir
+ * Contributors:
+ * All rights reserved.
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE CAFFEINE-HX PROJECT CONTRIBUTORS "AS
IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE CAFFEINE-HX PROJECT CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+package chx.crypt;
+
+/**
+ * Pads that work on blocks, and not on the full buffer.
+ **/
+class PadBlockBase extends PadBase {
+ /** the number of bytes that can fit in each block **/
+ public var textSize(default,null) : Int;
+
+ override public function isBlockPad() : Bool { return true; }
+
+ override public function calcNumBlocks(len : Int) : Int {
+ var ch : Int = blockSize - blockOverhead();
+ var n : Int = Math.ceil(len/ch);
+ if(len % blockSize == 0)
+ n++;
+ return n;
+ }
+
+ override public function getBytesReadPerBlock() : Int {
+ return blockSize - blockOverhead;
+ }
+
+ /**
+ * Returns the number of bytes padding needs per block
+ **/
+ public function blockOverhead() : Int {
+ return throw new chx.lang.FatalException("not implemented");
+ }
+}
=======================================
--- /dev/null
+++ /trunk/ext3/chx/crypt/rsa/PadPkcs1Type1.hx Mon Feb 20 10:13:32 2012
@@ -0,0 +1,138 @@
+/*
+ * Copyright (c) 2008, The Caffeine-hx project contributors
+ * Original author : Russell Weir
+ * Contributors:
+ * All rights reserved.
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE CAFFEINE-HX PROJECT CONTRIBUTORS "AS
IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE CAFFEINE-HX PROJECT CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+package chx.crypt;
+
+/**
+ Pads string with 0xFF bytes
+**/
+class PadPkcs1Type1 implements IBlockPad {
+ public var blockSize(default,setBlockSize) : Int;
+ public var textSize(default,null) : Int;
+ /** only for Type1, the byte to pad with, default 0xFF **/
+ public var padByte(getPadByte,setPadByte) : Int;
+ var padCount : Int;
+ var typeByte : Int;
+
+ public function new(size:Int) {
+ Reflect.setField(this,"blockSize",size);
+ setPadCount(8);
+ typeByte = 1;
+ padByte = 0xFF;
+ }
+
+ public function getBytesReadPerBlock() : Int {
+ return textSize;
+ }
+
+ public function pad( s : Bytes ) : Bytes {
+ if(s.length > textSize)
+ throw "Unable to pad block: provided buffer is " + s.length + " max
is " + textSize;
+ var sb = new BytesBuffer();
+ sb.addByte(0);
+ sb.addByte(typeByte);
+ var n = blockSize - s.length - 3; //padCount + (textSize - s.length);
+ while(n-- > 0) {
+ sb.addByte(getPadByte());
+ }
+ sb.addByte(0);
+ sb.add(s);
+
+ var rv = sb.getBytes();
+ #if CAFFEINE_DEBUG
+ trace("==Padded: " + BytesUtil.hexDump(rv));
+ #end
+ return rv;
+ }
+
+ public function unpad( s : Bytes ) : Bytes {
+ // src string may be shorter than block size. This happens when
+ // converting to BigIntegers then to padded string before calling
+ // unpad.
+ var i : Int = 0;
+ #if CAFFEINE_DEBUG
+ trace("==Unpadding Padded: " + BytesUtil.hexDump(s));
+ #end
+ var sb = new BytesBuffer();
+ while(i < s.length) {
+ while( i < s.length && s.get(i) == 0) ++i;
+ if(s.length-i-3-padCount < 0) {
+ throw("Unexpected short message");
+ }
+ if(s.get(i) != typeByte)
+ throw("Expected marker "+ typeByte + " at position "+i + " [" +
BytesUtil.hexDump(s) + "]");
+ if(++i >= s.length)
+ return sb.getBytes();
+ while(i < s.length && s.get(i) != 0) ++i;
+ i++;
+ var n : Int = 0;
+ while(i < s.length && n++ < textSize )
+ sb.addByte(s.get(i++));
+ }
+ return sb.getBytes();
+ }
+
+ public function calcNumBlocks(len : Int) : Int {
+ return Math.ceil(len/textSize);
+ }
+
+ /** pads by block? **/
+ public function isBlockPad() : Bool { return true; }
+
+ /** number of bytes padding needs per block **/
+ public function blockOverhead() : Int { return 3 + padCount; }
+
+ /**
+ PKCS1 has a 3 + padCount byte overhead per block. For RSA
+ padCount should be the default 8, for a total of 11 bytes
+ overhead per block.
+ **/
+ public function setPadCount(x : Int) : Int {
+ if(x + 3 >= blockSize)
+ throw("Internal padding size exceeds crypt block size");
+ padCount = x;
+ textSize = blockSize - 3 - padCount;
+ return x;
+ }
+
+ private function setBlockSize( x : Int ) : Int {
+ this.blockSize = x;
+ this.textSize = x - 3 - padCount;
+ if(textSize <= 0)
+ throw "Block size " + x + " to small for Pkcs1 with padCount "+padCount;
+ return x;
+ }
+
+ public function getPadByte() : Int {
+ return this.padByte;
+ }
+
+ public function setPadByte(x : Int) : Int {
+ this.padByte = x & 0xFF;
+ return x;
+ }
+}
=======================================
--- /dev/null
+++ /trunk/ext3/chx/crypt/rsa/PadPkcs1Type2.hx Mon Feb 20 10:13:32 2012
@@ -0,0 +1,49 @@
+/*
+ * Copyright (c) 2008, The Caffeine-hx project contributors
+ * Original author : Russell Weir
+ * Contributors:
+ * All rights reserved.
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE CAFFEINE-HX PROJECT CONTRIBUTORS "AS
IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE CAFFEINE-HX PROJECT CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+package chx.crypt;
+
+import math.prng.Random;
+
+/**
+ * Pads buffer with random bytes
+ **/
+class PadPkcs1Type2 extends PadPkcs1Type1, implements IBlockPad {
+ var rng : Random;
+
+ public function new( size : Int ) {
+ super(size);
+ typeByte = 2;
+ rng = new Random();
+ }
+
+ override public function getPadByte() : Int {
+ var x: Int = 0;
+ while(x == 0) x = rng.next();
+ return x;
+ }
+}
=======================================
--- /dev/null
+++ /trunk/ext3/chx/crypt/rsa/RSA.hx Mon Feb 20 10:13:32 2012
@@ -0,0 +1,276 @@
+/*
+ * Copyright (c) 2008, The Caffeine-hx project contributors
+ * Original author : Russell Weir
+ * Contributors:
+ * All rights reserved.
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE CAFFEINE-HX PROJECT CONTRIBUTORS "AS
IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE CAFFEINE-HX PROJECT CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+/*
+ * Derived from javascript implementation Copyright (c) 2005 Tom Wu
+ */
+
+package chx.crypt;
+
+import math.BigInteger;
+
+/**
+ Full RSA encryption class. For encryption only, the base class
+ RSAEncrypt can be used instead.
+**/
+class RSA extends RSAEncrypt, implements IBlockCipher {
+ public var d : BigInteger; // private key
+ public var p : BigInteger; // prime 1
+ public var q : BigInteger; // prime 2
+ public var dmp1 : BigInteger; // d % (p-1)
+ public var dmq1 : BigInteger; // d % (q -1)
+ public var coeff: BigInteger;
+
+ public function new(nHex:String=null,eHex:String=null,dHex:String=null) {
+ super(null,null);
+ init();
+ if(nHex != null)
+ setPrivate(nHex,eHex,dHex);
+ }
+
+ override private function init() {
+ super.init();
+ this.d = null; // private exponent
+ this.p = null; // prime 1
+ this.q = null; // prime 2
+ this.dmp1 = null; // d % (p-1)
+ this.dmq1 = null; // d % (q -1)
+ this.coeff = null;
+ }
+
+ /**
+ * Return the PKCS#1 RSA decryption of "ctext", an even-length hex string.
+ *
+ * @param ctext Hexadecimal string
+ **/
+ public function decrypt( buf : Bytes ) : Bytes {
+ return doBufferDecrypt(buf, doPrivate, new PadPkcs1Type2(blockSize));
+ }
+
+ /**
+ *
+ **/
+ override public function decryptBlock( enc : Bytes ) : Bytes {
+ var c : BigInteger = BigInteger.ofBytes(enc, true);
+ var m : BigInteger = doPrivate(c);
+ if(m == null)
+ throw "doPrivate error";
+
+ // the encrypted block is a BigInteger, so any leading
+ // 0's will have been truncated. Push them back in.
+ var ba = m.toBytesUnsigned();
+ if(ba.length < blockSize) {
+ var b2 = Bytes.alloc(blockSize);
+ for(i in 0...blockSize - ba.length + 1)
+ b2.set(i, 0);
+ b2.blit(blockSize - ba.length, ba, 0, ba.length);
+ ba = b2;
+ }
+ else {
+ while(ba.length > blockSize) {
+ var cnt = ba.length - blockSize;
+ for(i in 0...cnt)
+ if(ba.get(i) != 0)
+ throw "decryptBlock length error";
+ ba = ba.sub(cnt, blockSize);
+ }
+ }
+ return ba;
+ }
+
+ /**
+ * Return the PKCS#1 RSA decryption of "text", which is any valid
+ * hex string, optionally separated w with : or whitespace as
+ * a separator character.
+ *
+ * @param hexString Hexadecimal string
+ * @return Bytes of decrypted data
+ **/
+ public function decryptText( hexString : String ) : Bytes {
+ return decrypt( BytesUtil.ofHex(BytesUtil.cleanHexFormat(hexString)) );
+ }
+
+ /**
+ * Generate a new random private key B bits long, using public expt E.
+ * Generating keys over 512 bits in neko, or 256 bit on other platforms
+ * is just not practical. If you need large keys, generate them with
+ * openssl and load them into RSA.<br />
+ * <b>openssl genrsa -des3 -out user.key 1024</b><br />
+ * <b>openssl genrsa -3 -out user.key 1024</b> no password, 3 as
exponent<br />
+ * will generate a 1024 bit key, which can be displayed with<br />
+ * <b>openssl rsa -in user.key -noout -text</b>
+ *
+ * @param B Number of bits for key
+ * @param E public exponent, a hexadecimal string
+ */
+ public static function generate(B:Int, E:String) : RSA {
+ var rng = new math.prng.Random();
+ var key:RSA = new RSA();
+ var qs : Int = B>>1;
+ key.e = Std.parseInt(StringTools.startsWith(E, "0x") ? E : "0x" + E);
+ var ee : BigInteger = BigInteger.ofInt(key.e);
+ while(true) {
+ key.p = BigInteger.randomPrime(B-qs, ee, 10, true, rng);
+ key.q = BigInteger.randomPrime(qs, ee, 10, true, rng);
+ if(key.p.compare(key.q) <= 0) {
+ var t = key.p;
+ key.p = key.q;
+ key.q = t;
+ }
+ var p1:BigInteger = key.p.sub(BigInteger.ONE);
+ var q1:BigInteger = key.q.sub(BigInteger.ONE);
+ var phi:BigInteger = p1.mul(q1);
+ if(phi.gcd(ee).compare(BigInteger.ONE) == 0) {
+ key.n = key.p.mul(key.q);
+ key.d = ee.modInverse(phi);
+ key.dmp1 = key.d.mod(p1);
+ key.dmq1 = key.d.mod(q1);
+ key.coeff = key.q.modInverse(key.p);
+ break;
+ }
+ }
+ return key;
+ }
+
+ /**
+ * Sign a certificate
+ *
+ * @param content buffer string
+ **/
+ public function sign( content : Bytes ) : Bytes {
+ return doBufferEncrypt(content, doPrivate, new PadPkcs1Type1(blockSize));
+ }
+
+ /**
+ * Set the private key fields N (modulus), E (public exponent)
+ * and D (private exponent) from hex strings.
+ *
+ * @param N modulus, a hexadecimal string
+ * @param E public exponent, a hexadecimal string
+ * @param D private exponent, a hexadecimal string
+ * @throws String on errors
+ **/
+ public function setPrivate(N:String,E:String,D:String) : Void {
+ init();
+ super.setPublic(N, E);
+ if(D != null && D.length > 0) {
+ var s = BytesUtil.cleanHexFormat(D);
+ d = BigInteger.ofString(s, 16);
+ }
+ else
+ throw("Invalid RSA private key");
+ }
+
+ /**
+ * Set the private key fields N, E, D and CRT params from
+ * hex strings.
+ *
+ * @param N modulus, a hexadecimal string
+ * @param E public exponent, a hexadecimal string
+ * @param D private exponent, a hexadecimal string
+ * @param P prime1, a hexadecimal string
+ * @param Q prime2, a hexadecimal string
+ * @param DP d % (p-1), a hexadecimal string or null
+ * @param DQ d % (q-1), a hexadecimal string or null
+ * @param C coefficient, a hexadecimal string
+ * @throws String on errors
+ **/
+ public function setPrivateEx(
+ N:String,E:String,D:String,P:String,Q:String,
+ DP:String=null,DQ:String=null,C:String=null) : Void
+ {
+ init();
+ setPrivate(N, E, D);
+ if(P != null && Q != null)
+ {
+ p = BigInteger.ofString(BytesUtil.cleanHexFormat(P), 16);
+ q = BigInteger.ofString(BytesUtil.cleanHexFormat(Q), 16);
+
+ dmp1 = null;
+ dmq1 = null;
+ coeff = null;
+
+ if(DP != null)
+ dmp1 = BigInteger.ofString(BytesUtil.cleanHexFormat(DP),16);
+
+ if(DQ != null)
+ dmq1 = BigInteger.ofString(BytesUtil.cleanHexFormat(DQ),16);
+
+ if(C != null)
+ coeff = BigInteger.ofString(BytesUtil.cleanHexFormat(C), 16);
+
+ recalcCRT();
+ }
+ else
+ throw("Invalid RSA private key ex");
+ }
+
+ function recalcCRT() {
+ if(p != null && q != null) {
+ if(dmp1 == null)
+ dmp1 = d.mod(p.sub(BigInteger.ONE));
+ if(dmq1 == null)
+ dmq1 = d.mod(q.sub(BigInteger.ONE));
+ if(coeff == null)
+ coeff = q.modInverse(p);
+ }
+ }
+
+ //////////////////////////////////////////////////
+ // Private //
+ //////////////////////////////////////////////////
+ /**
+ Perform raw private operation on "x": return x^d (mod n)
+ **/
+ function doPrivate( x:BigInteger ) : BigInteger {
+ if(this.p == null || this.q == null) {
+ return x.modPow(this.d, this.n);
+ }
+
+ var xp = x.mod(this.p).modPow(this.dmp1, this.p);
+ var xq = x.mod(this.q).modPow(this.dmq1, this.q);
+
+ while(xp.compare(xq) < 0)
+ xp = xp.add(this.p);
+ return xp.sub(xq).mul(this.coeff).mod(this.p).mul(this.q).add(xq);
+ }
+
+ /*
+ override public function toString() {
+ var sb = new StringBuf();
+ sb.add(super.toString());
+ sb.add("Private:\n");
+ sb.add("D:\t" + d.toHex() + "\n");
+ if(p != null) sb.add("P:\t" + p.toHex() + "\n");
+ if(q != null) sb.add("Q:\t" + q.toHex() + "\n");
+ if(dmp1 != null) sb.add("DMP1:\t" + dmp1.toHex() + "\n");
+ if(dmq1 != null) sb.add("DMQ1:\t" + dmq1.toHex() + "\n");
+ if(coeff != null) sb.add("COEFF:\t" + coeff.toHex() + "\n");
+ return sb.toString();
+ }
+ */
+}
+
=======================================
--- /dev/null
+++ /trunk/ext3/chx/crypt/rsa/RSAEncrypt.hx Mon Feb 20 10:13:32 2012
@@ -0,0 +1,278 @@
+/*
+ * Copyright (c) 2008, The Caffeine-hx project contributors
+ * Original author : Russell Weir
+ * Contributors:
+ * All rights reserved.
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE CAFFEINE-HX PROJECT CONTRIBUTORS "AS
IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE CAFFEINE-HX PROJECT CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*
+ * Derived from javascript implementation Copyright (c) 2005 Tom Wu
+ *
+ */
+
+package chx.crypt;
+
+import math.BigInteger;
+import math.prng.Random;
+
+/**
+ RSAEncrypt encrypts using a provided public key. If decryption is
+ required, use the derived class RSADecrypt which can encypt and decrypt.
+**/
+class RSAEncrypt implements IBlockCipher {
+ // public key
+ /** modulus **/
+ public var n : BigInteger;
+ /** exponent. <2^31 **/
+ public var e : Int;
+ public var blockSize(__getBlockSize,null) : Int;
+
+ public function new(nHex:String,eHex:String) {
+ init();
+ if(nHex != null)
+ setPublic(nHex, eHex);
+ }
+
+ private function init() {
+ this.n = null;
+ this.e = 0;
+ }
+
+ /**
+ * Decrypts a pre-padded buffer.
+ *
+ * @param block Block of encrypted data that must be exactly blockSize long
+ * @return blockSize buffer with decrypted data.
+ **/
+ public function decryptBlock( enc : Bytes ) : Bytes {
+ throw("Not a private key");
+ return null;
+ }
+
+ /**
+ * Return the PKCS#1 RSA encryption of [buf]
+ *
+ * @param buf plaintext buffer
+ * TODO: Return Binary string, not text. Use padding etc...
+ **/
+ public function encrypt( buf : Bytes ) : Bytes {
+ return doBufferEncrypt(buf, doPublic, new PadPkcs1Type2(blockSize));
+ }
+
+ /**
+ * Encrypt a pre-padded buffer.
+ *
+ * @param block Block of plaintext that must be exactly blockSize long
+ * @return blockSize buffer with crypted data.
+ **/
+ public function encryptBlock( block : Bytes ) : Bytes {
+ var bsize : Int = blockSize;
+ if(block.length != bsize)
+ throw("bad block size");
+
+ var biv:BigInteger = BigInteger.ofBytes(block, true);
+ var biRes = doPublic(biv).toBytesUnsigned();
+
+ var l = biRes.length;
+ var i = 0;
+ while(l > bsize) {
+ if(biRes.get(i) != 0) {
+ throw new chx.lang.FatalException("encoded length was "+biRes.length);
+ }
+ i++; l--;
+ }
+ if(i != 0) {
+ biRes = biRes.sub(i, l);
+ }
+
+ if(biRes.length < bsize) {
+ var bb = new BytesBuffer();
+ l = bsize - biRes.length;
+ for(i in 0...l)
+ bb.addByte(0);
+ bb.addBytes(biRes, 0, biRes.length);
+ biRes = bb.getBytes();
+ }
+ return biRes;
+ }
+
+ /**
+ * Return the PKCS#1 RSA encryption of "text" as an hex string, with [:] as
+ * a separator character.
+ *
+ * @param text Text to encrypt.
+ * @param separator character to put between hex values in output
+ **/
+ public function encyptText( text : String, separator:String = ":") :
String {
+ return BytesUtil.toHex(
+ encrypt( Bytes.ofString(text) ),
+ ":");
+ }
+
+ /**
+ * Set the public key fields N (modulus) and E (public exponent)
+ * from hex strings.
+ **/
+ public function setPublic(nHex : String, eHex:String) : Void {
+ init();
+ if(nHex == null || nHex.length == 0)
+ throw new chx.lang.NullPointerException("nHex not set: " + nHex);
+ if(eHex == null || eHex.length == 0)
+ throw new chx.lang.NullPointerException("eHex not set: " + eHex);
+ //try {
+ var s : String = BytesUtil.cleanHexFormat(nHex);
+ n = BigInteger.ofString(s, 16);
+ if(n == null) throw 2;
+ var ie : Null<Int> = Std.parseInt("0x" +
BytesUtil.cleanHexFormat(eHex));
+ if(ie == null || ie == 0) throw 3;
+ e = ie;
+ //}
+ //catch(e:Dynamic)
+ // throw("Invalid RSA public key: " + e);
+ }
+
+ /**
+ * Verify a signature
+ *
+ * @todo http://www.imc.org/ietf-openpgp/mail-archive/msg14307.html
+ * @todo verify implementation
+ **/
+ public function verify( data : Bytes ) : Bytes {
+ return doBufferDecrypt(data, doPublic, new PadPkcs1Type1(blockSize));
+ }
+
+
+ //////////////////////////////////////////////////
+ // Private //
+ //////////////////////////////////////////////////
+ /**
+ * Encrypts a bytes buffer
+ *
+ * @param src Input bytes
+ * @param f Callback for encryption
+ * @param pf Padding method
+ **/
+ private function doBufferEncrypt(src:Bytes, f : BigInteger->BigInteger,
pf : IBlockPad) : Bytes
+ {
+ //trace("source: " + src.toHex());
+ var bs = blockSize;
+ var ts : Int = bs - 11;
+ #if CAFFEINE_DEBUG
+ trace(">>>> Encrypting. Blocksize is "+bs + " src length:"+src.length
+ "["+src.toHex()+"]");
+ #end
+ var idx : Int = 0;
+ var msg = new BytesBuffer();
+ while(idx < src.length) {
+ if(idx + ts > src.length)
+ ts = src.length - idx;
+ var m:BigInteger = BigInteger.ofBytes(pf.pad(src.sub(idx,ts)), true);
+ var c:BigInteger = f(m);
+
+ #if CAFFEINE_DEBUG
+ var d = m.toBytesUnsigned();
+ var e = c.toBytesUnsigned();
+ trace("m (padded) len " + d.length + " "+d.toHex(":"));
+ trace("c (crypted) len " + e.length + " "+e.toHex(":"));
+ #end
+
+ var h = c.toBytesUnsigned();
+ //var
+ if((h.length & 1) != 0)
+ msg.addByte( 0 );
+
+ #if CAFFEINE_DEBUG
+ trace(">>>> crypted ("+h.length+"): " + h.toHex());
+ #end
+
+ msg.add(h);
+ idx += ts;
+ }
+ return msg.getBytes();
+ }
+
+ private function doBufferDecrypt(src: Bytes, f : BigInteger->BigInteger,
pf : IBlockPad) : Bytes
+ {
+ //trace("source: " + src.toHex());
+ var bs = blockSize;
+ //bs *= 2; // hex string, 2 bytes per char
+ var ts : Int = bs - 11;
+ #if CAFFEINE_DEBUG
+ trace(">>>> Decrypting. Blocksize is "+ bs + " src length:"+src.length
+ "["+src.toHex()+"]");
+ #end
+ var idx : Int = 0;
+ var msg = new BytesBuffer();
+ while(idx < src.length) {
+ if(idx + bs > src.length)
+ bs = src.length - idx;
+ var c : BigInteger = BigInteger.ofBytes(src.sub(idx,bs), true);
+ var m = f(c);
+ if(m == null)
+ return null;
+
+ #if CAFFEINE_DEBUG
+ var d = m.toBytesUnsigned();
+ var e = c.toBytesUnsigned();
+ trace("c (crypted) len " + e.length + " "+e.toHex(":"));
+ trace("m (padded) len " + d.length + " "+d.toHex(":"));
+ #end
+
+ var up : Bytes = pf.unpad(m.toBytesUnsigned());
+ if(up.length > ts)
+ throw "block text length error";
+ msg.add(up);
+ idx += bs;
+ }
+ return msg.getBytes();
+ }
+
+ // Perform raw public operation on "x": return x^e (mod n)
+ function doPublic(x : BigInteger) : BigInteger {
+ return x.modPowInt(this.e, this.n);
+ }
+
+ //////////////////////////////////////////////////
+ // getters/setters //
+ //////////////////////////////////////////////////
+ function __getBlockSize() : Int {
+ if(n == null)
+ return 0;
+ return (n.bitLength()+7)>>3;
+ }
+
+ //////////////////////////////////////////////////
+ // Convenience //
+ //////////////////////////////////////////////////
+
+
+ public function toString() {
+ return "rsa";
+ /*
+ var sb = new StringBuf();
+ sb.add("Public:\n");
+ sb.add("N:\t" + n.toHex() + "\n");
+ sb.add("E:\t" + BigInteger.ofInt(e).toHex() + "\n");
+ return sb.toString();
+ */
+ }
+}
+
=======================================
--- /trunk/ext3/chx/crypt/IBlockPad.hx Tue Jan 10 15:06:09 2012
+++ /dev/null
@@ -1,50 +0,0 @@
-/*
- * Copyright (c) 2012, The Caffeine-hx project contributors
- * Original author : Russell Weir
- * Contributors:
- * All rights reserved.
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
met:
- *
- * - Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * - Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE CAFFEINE-HX PROJECT CONTRIBUTORS "AS
IS"
- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE CAFFEINE-HX PROJECT CONTRIBUTORS
- * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
- * THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-package chx.crypt;
-
-interface IBlockPad {
- /** finished padded block size **/
- var blockSize(default,setBlockSize) : Int;
-
- function pad( s : Bytes ) : Bytes;
-
- function unpad( s : Bytes ) : Bytes;
-
- /** returns the number of blocks for message length len **/
- function calcNumBlocks(len : Int) : Int;
-
- /** number of bytes padding needs per block **/
- function blockOverhead() : Int;
-
- /**
- * Number of bytes of source material that will actually be written into
each block.
- * On block pads, this will be less than the block size.
(blockSize-blockOverhead)
- **/
- function getBytesReadPerBlock() : Int;
-
-}
=======================================
--- /trunk/ext3/chx/crypt/PadBlockBase.hx Mon Apr 11 20:26:42 2011
+++ /dev/null
@@ -1,57 +0,0 @@
-/*
- * Copyright (c) 2011, The Caffeine-hx project contributors
- * Original author : Russell Weir
- * Contributors:
- * All rights reserved.
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
met:
- *
- * - Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * - Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE CAFFEINE-HX PROJECT CONTRIBUTORS "AS
IS"
- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE CAFFEINE-HX PROJECT CONTRIBUTORS
- * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
- * THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-package chx.crypt;
-
-/**
- * Pads that work on blocks, and not on the full buffer.
- **/
-class PadBlockBase extends PadBase {
- /** the number of bytes that can fit in each block **/
- public var textSize(default,null) : Int;
-
- override public function isBlockPad() : Bool { return true; }
-
- override public function calcNumBlocks(len : Int) : Int {
- var ch : Int = blockSize - blockOverhead();
- var n : Int = Math.ceil(len/ch);
- if(len % blockSize == 0)
- n++;
- return n;
- }
-
- override public function getBytesReadPerBlock() : Int {
- return blockSize - blockOverhead;
- }
-
- /**
- * Returns the number of bytes padding needs per block
- **/
- public function blockOverhead() : Int {
- return throw new chx.lang.FatalException("not implemented");
- }
-}
=======================================
--- /trunk/ext3/chx/crypt/PadPkcs1Type1.hx Tue Jan 10 15:06:09 2012
+++ /dev/null
@@ -1,138 +0,0 @@
-/*
- * Copyright (c) 2008, The Caffeine-hx project contributors
- * Original author : Russell Weir
- * Contributors:
- * All rights reserved.
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
met:
- *
- * - Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * - Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE CAFFEINE-HX PROJECT CONTRIBUTORS "AS
IS"
- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE CAFFEINE-HX PROJECT CONTRIBUTORS
- * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
- * THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-package chx.crypt;
-
-/**
- Pads string with 0xFF bytes
-**/
-class PadPkcs1Type1 implements IBlockPad {
- public var blockSize(default,setBlockSize) : Int;
- public var textSize(default,null) : Int;
- /** only for Type1, the byte to pad with, default 0xFF **/
- public var padByte(getPadByte,setPadByte) : Int;
- var padCount : Int;
- var typeByte : Int;
-
- public function new(size:Int) {
- Reflect.setField(this,"blockSize",size);
- setPadCount(8);
- typeByte = 1;
- padByte = 0xFF;
- }
-
- public function getBytesReadPerBlock() : Int {
- return textSize;
- }
-
- public function pad( s : Bytes ) : Bytes {
- if(s.length > textSize)
- throw "Unable to pad block: provided buffer is " + s.length + " max
is " + textSize;
- var sb = new BytesBuffer();
- sb.addByte(0);
- sb.addByte(typeByte);
- var n = blockSize - s.length - 3; //padCount + (textSize - s.length);
- while(n-- > 0) {
- sb.addByte(getPadByte());
- }
- sb.addByte(0);
- sb.add(s);
-
- var rv = sb.getBytes();
- #if CAFFEINE_DEBUG
- trace("==Padded: " + BytesUtil.hexDump(rv));
- #end
- return rv;
- }
-
- public function unpad( s : Bytes ) : Bytes {
- // src string may be shorter than block size. This happens when
- // converting to BigIntegers then to padded string before calling
- // unpad.
- var i : Int = 0;
- #if CAFFEINE_DEBUG
- trace("==Unpadding Padded: " + BytesUtil.hexDump(s));
- #end
- var sb = new BytesBuffer();
- while(i < s.length) {
- while( i < s.length && s.get(i) == 0) ++i;
- if(s.length-i-3-padCount < 0) {
- throw("Unexpected short message");
- }
- if(s.get(i) != typeByte)
- throw("Expected marker "+ typeByte + " at position "+i + " [" +
BytesUtil.hexDump(s) + "]");
- if(++i >= s.length)
- return sb.getBytes();
- while(i < s.length && s.get(i) != 0) ++i;
- i++;
- var n : Int = 0;
- while(i < s.length && n++ < textSize )
- sb.addByte(s.get(i++));
- }
- return sb.getBytes();
- }
-
- public function calcNumBlocks(len : Int) : Int {
- return Math.ceil(len/textSize);
- }
-
- /** pads by block? **/
- public function isBlockPad() : Bool { return true; }
-
- /** number of bytes padding needs per block **/
- public function blockOverhead() : Int { return 3 + padCount; }
-
- /**
- PKCS1 has a 3 + padCount byte overhead per block. For RSA
- padCount should be the default 8, for a total of 11 bytes
- overhead per block.
- **/
- public function setPadCount(x : Int) : Int {
- if(x + 3 >= blockSize)
- throw("Internal padding size exceeds crypt block size");
- padCount = x;
- textSize = blockSize - 3 - padCount;
- return x;
- }
-
- private function setBlockSize( x : Int ) : Int {
- this.blockSize = x;
- this.textSize = x - 3 - padCount;
- if(textSize <= 0)
- throw "Block size " + x + " to small for Pkcs1 with padCount "+padCount;
- return x;
- }
-
- public function getPadByte() : Int {
- return this.padByte;
- }
-
- public function setPadByte(x : Int) : Int {
- this.padByte = x & 0xFF;
- return x;
- }
-}
=======================================
--- /trunk/ext3/chx/crypt/PadPkcs1Type2.hx Tue Jan 10 15:06:09 2012
+++ /dev/null
@@ -1,49 +0,0 @@
-/*
- * Copyright (c) 2008, The Caffeine-hx project contributors
- * Original author : Russell Weir
- * Contributors:
- * All rights reserved.
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
met:
- *
- * - Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * - Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE CAFFEINE-HX PROJECT CONTRIBUTORS "AS
IS"
- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE CAFFEINE-HX PROJECT CONTRIBUTORS
- * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
- * THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-package chx.crypt;
-
-import math.prng.Random;
-
-/**
- * Pads buffer with random bytes
- **/
-class PadPkcs1Type2 extends PadPkcs1Type1, implements IBlockPad {
- var rng : Random;
-
- public function new( size : Int ) {
- super(size);
- typeByte = 2;
- rng = new Random();
- }
-
- override public function getPadByte() : Int {
- var x: Int = 0;
- while(x == 0) x = rng.next();
- return x;
- }
-}
=======================================
--- /trunk/ext3/chx/crypt/RSA.hx Tue Jan 10 15:06:09 2012
+++ /dev/null
@@ -1,276 +0,0 @@
-/*
- * Copyright (c) 2008, The Caffeine-hx project contributors
- * Original author : Russell Weir
- * Contributors:
- * All rights reserved.
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
met:
- *
- * - Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * - Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE CAFFEINE-HX PROJECT CONTRIBUTORS "AS
IS"
- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE CAFFEINE-HX PROJECT CONTRIBUTORS
- * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
- * THE POSSIBILITY OF SUCH DAMAGE.
- */
-/*
- * Derived from javascript implementation Copyright (c) 2005 Tom Wu
- */
-
-package chx.crypt;
-
-import math.BigInteger;
-
-/**
- Full RSA encryption class. For encryption only, the base class
- RSAEncrypt can be used instead.
-**/
-class RSA extends RSAEncrypt, implements IBlockCipher {
- public var d : BigInteger; // private key
- public var p : BigInteger; // prime 1
- public var q : BigInteger; // prime 2
- public var dmp1 : BigInteger; // d % (p-1)
- public var dmq1 : BigInteger; // d % (q -1)
- public var coeff: BigInteger;
-
- public function new(nHex:String=null,eHex:String=null,dHex:String=null) {
- super(null,null);
- init();
- if(nHex != null)
- setPrivate(nHex,eHex,dHex);
- }
-
- override private function init() {
- super.init();
- this.d = null; // private exponent
- this.p = null; // prime 1
- this.q = null; // prime 2
- this.dmp1 = null; // d % (p-1)
- this.dmq1 = null; // d % (q -1)
- this.coeff = null;
- }
-
- /**
- * Return the PKCS#1 RSA decryption of "ctext", an even-length hex string.
- *
- * @param ctext Hexadecimal string
- **/
- public function decrypt( buf : Bytes ) : Bytes {
- return doBufferDecrypt(buf, doPrivate, new PadPkcs1Type2(blockSize));
- }
-
- /**
- *
- **/
- override public function decryptBlock( enc : Bytes ) : Bytes {
- var c : BigInteger = BigInteger.ofBytes(enc, true);
- var m : BigInteger = doPrivate(c);
- if(m == null)
- throw "doPrivate error";
-
- // the encrypted block is a BigInteger, so any leading
- // 0's will have been truncated. Push them back in.
- var ba = m.toBytesUnsigned();
- if(ba.length < blockSize) {
- var b2 = Bytes.alloc(blockSize);
- for(i in 0...blockSize - ba.length + 1)
- b2.set(i, 0);
- b2.blit(blockSize - ba.length, ba, 0, ba.length);
- ba = b2;
- }
- else {
- while(ba.length > blockSize) {
- var cnt = ba.length - blockSize;
- for(i in 0...cnt)
- if(ba.get(i) != 0)
- throw "decryptBlock length error";
- ba = ba.sub(cnt, blockSize);
- }
- }
- return ba;
- }
-
- /**
- * Return the PKCS#1 RSA decryption of "text", which is any valid
- * hex string, optionally separated w with : or whitespace as
- * a separator character.
- *
- * @param hexString Hexadecimal string
- * @return Bytes of decrypted data
- **/
- public function decryptText( hexString : String ) : Bytes {
- return decrypt( BytesUtil.ofHex(BytesUtil.cleanHexFormat(hexString)) );
- }
-
- /**
- * Generate a new random private key B bits long, using public expt E.
- * Generating keys over 512 bits in neko, or 256 bit on other platforms
- * is just not practical. If you need large keys, generate them with
- * openssl and load them into RSA.<br />
- * <b>openssl genrsa -des3 -out user.key 1024</b><br />
- * <b>openssl genrsa -3 -out user.key 1024</b> no password, 3 as
exponent<br />
- * will generate a 1024 bit key, which can be displayed with<br />
- * <b>openssl rsa -in user.key -noout -text</b>
- *
- * @param B Number of bits for key
- * @param E public exponent, a hexadecimal string
- */
- public static function generate(B:Int, E:String) : RSA {
- var rng = new math.prng.Random();
- var key:RSA = new RSA();
- var qs : Int = B>>1;
- key.e = Std.parseInt(StringTools.startsWith(E, "0x") ? E : "0x" + E);
- var ee : BigInteger = BigInteger.ofInt(key.e);
- while(true) {
- key.p = BigInteger.randomPrime(B-qs, ee, 10, true, rng);
- key.q = BigInteger.randomPrime(qs, ee, 10, true, rng);
- if(key.p.compare(key.q) <= 0) {
- var t = key.p;
- key.p = key.q;
- key.q = t;
- }
- var p1:BigInteger = key.p.sub(BigInteger.ONE);
- var q1:BigInteger = key.q.sub(BigInteger.ONE);
- var phi:BigInteger = p1.mul(q1);
- if(phi.gcd(ee).compare(BigInteger.ONE) == 0) {
- key.n = key.p.mul(key.q);
- key.d = ee.modInverse(phi);
- key.dmp1 = key.d.mod(p1);
- key.dmq1 = key.d.mod(q1);
- key.coeff = key.q.modInverse(key.p);
- break;
- }
- }
- return key;
- }
-
- /**
- * Sign a certificate
- *
- * @param content buffer string
- **/
- public function sign( content : Bytes ) : Bytes {
- return doBufferEncrypt(content, doPrivate, new PadPkcs1Type1(blockSize));
- }
-
- /**
- * Set the private key fields N (modulus), E (public exponent)
- * and D (private exponent) from hex strings.
- *
- * @param N modulus, a hexadecimal string
- * @param E public exponent, a hexadecimal string
- * @param D private exponent, a hexadecimal string
- * @throws String on errors
- **/
- public function setPrivate(N:String,E:String,D:String) : Void {
- init();
- super.setPublic(N, E);
- if(D != null && D.length > 0) {
- var s = BytesUtil.cleanHexFormat(D);
- d = BigInteger.ofString(s, 16);
- }
- else
- throw("Invalid RSA private key");
- }
-
- /**
- * Set the private key fields N, E, D and CRT params from
- * hex strings.
- *
- * @param N modulus, a hexadecimal string
- * @param E public exponent, a hexadecimal string
- * @param D private exponent, a hexadecimal string
- * @param P prime1, a hexadecimal string
- * @param Q prime2, a hexadecimal string
- * @param DP d % (p-1), a hexadecimal string or null
- * @param DQ d % (q-1), a hexadecimal string or null
- * @param C coefficient, a hexadecimal string
- * @throws String on errors
- **/
- public function setPrivateEx(
- N:String,E:String,D:String,P:String,Q:String,
- DP:String=null,DQ:String=null,C:String=null) : Void
- {
- init();
- setPrivate(N, E, D);
- if(P != null && Q != null)
- {
- p = BigInteger.ofString(BytesUtil.cleanHexFormat(P), 16);
- q = BigInteger.ofString(BytesUtil.cleanHexFormat(Q), 16);
-
- dmp1 = null;
- dmq1 = null;
- coeff = null;
-
- if(DP != null)
- dmp1 = BigInteger.ofString(BytesUtil.cleanHexFormat(DP),16);
-
- if(DQ != null)
- dmq1 = BigInteger.ofString(BytesUtil.cleanHexFormat(DQ),16);
-
- if(C != null)
- coeff = BigInteger.ofString(BytesUtil.cleanHexFormat(C), 16);
-
- recalcCRT();
- }
- else
- throw("Invalid RSA private key ex");
- }
-
- function recalcCRT() {
- if(p != null && q != null) {
- if(dmp1 == null)
- dmp1 = d.mod(p.sub(BigInteger.ONE));
- if(dmq1 == null)
- dmq1 = d.mod(q.sub(BigInteger.ONE));
- if(coeff == null)
- coeff = q.modInverse(p);
- }
- }
-
- //////////////////////////////////////////////////
- // Private //
- //////////////////////////////////////////////////
- /**
- Perform raw private operation on "x": return x^d (mod n)
- **/
- function doPrivate( x:BigInteger ) : BigInteger {
- if(this.p == null || this.q == null) {
- return x.modPow(this.d, this.n);
- }
-
- var xp = x.mod(this.p).modPow(this.dmp1, this.p);
- var xq = x.mod(this.q).modPow(this.dmq1, this.q);
-
- while(xp.compare(xq) < 0)
- xp = xp.add(this.p);
- return xp.sub(xq).mul(this.coeff).mod(this.p).mul(this.q).add(xq);
- }
-
- /*
- override public function toString() {
- var sb = new StringBuf();
- sb.add(super.toString());
- sb.add("Private:\n");
- sb.add("D:\t" + d.toHex() + "\n");
- if(p != null) sb.add("P:\t" + p.toHex() + "\n");
- if(q != null) sb.add("Q:\t" + q.toHex() + "\n");
- if(dmp1 != null) sb.add("DMP1:\t" + dmp1.toHex() + "\n");
- if(dmq1 != null) sb.add("DMQ1:\t" + dmq1.toHex() + "\n");
- if(coeff != null) sb.add("COEFF:\t" + coeff.toHex() + "\n");
- return sb.toString();
- }
- */
-}
-
=======================================
--- /trunk/ext3/chx/crypt/RSAEncrypt.hx Tue Jan 10 15:06:09 2012
+++ /dev/null
@@ -1,278 +0,0 @@
-/*
- * Copyright (c) 2008, The Caffeine-hx project contributors
- * Original author : Russell Weir
- * Contributors:
- * All rights reserved.
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
met:
- *
- * - Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * - Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE CAFFEINE-HX PROJECT CONTRIBUTORS "AS
IS"
- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE CAFFEINE-HX PROJECT CONTRIBUTORS
- * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
- * THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-/*
- * Derived from javascript implementation Copyright (c) 2005 Tom Wu
- *
- */
-
-package chx.crypt;
-
-import math.BigInteger;
-import math.prng.Random;
-
-/**
- RSAEncrypt encrypts using a provided public key. If decryption is
- required, use the derived class RSADecrypt which can encypt and decrypt.
-**/
-class RSAEncrypt implements IBlockCipher {
- // public key
- /** modulus **/
- public var n : BigInteger;
- /** exponent. <2^31 **/
- public var e : Int;
- public var blockSize(__getBlockSize,null) : Int;
-
- public function new(nHex:String,eHex:String) {
- init();
- if(nHex != null)
- setPublic(nHex, eHex);
- }
-
- private function init() {
- this.n = null;
- this.e = 0;
- }
-
- /**
- * Decrypts a pre-padded buffer.
- *
- * @param block Block of encrypted data that must be exactly blockSize long
- * @return blockSize buffer with decrypted data.
- **/
- public function decryptBlock( enc : Bytes ) : Bytes {
- throw("Not a private key");
- return null;
- }
-
- /**
- * Return the PKCS#1 RSA encryption of [buf]
- *
- * @param buf plaintext buffer
- * TODO: Return Binary string, not text. Use padding etc...
- **/
- public function encrypt( buf : Bytes ) : Bytes {
- return doBufferEncrypt(buf, doPublic, new PadPkcs1Type2(blockSize));
- }
-
- /**
- * Encrypt a pre-padded buffer.
- *
- * @param block Block of plaintext that must be exactly blockSize long
- * @return blockSize buffer with crypted data.
- **/
- public function encryptBlock( block : Bytes ) : Bytes {
- var bsize : Int = blockSize;
- if(block.length != bsize)
- throw("bad block size");
-
- var biv:BigInteger = BigInteger.ofBytes(block, true);
- var biRes = doPublic(biv).toBytesUnsigned();
-
- var l = biRes.length;
- var i = 0;
- while(l > bsize) {
- if(biRes.get(i) != 0) {
- throw new chx.lang.FatalException("encoded length was "+biRes.length);
- }
- i++; l--;
- }
- if(i != 0) {
- biRes = biRes.sub(i, l);
- }
-
- if(biRes.length < bsize) {
- var bb = new BytesBuffer();
- l = bsize - biRes.length;
- for(i in 0...l)
- bb.addByte(0);
- bb.addBytes(biRes, 0, biRes.length);
- biRes = bb.getBytes();
- }
- return biRes;
- }
-
- /**
- * Return the PKCS#1 RSA encryption of "text" as an hex string, with [:] as
- * a separator character.
- *
- * @param text Text to encrypt.
- * @param separator character to put between hex values in output
- **/
- public function encyptText( text : String, separator:String = ":") :
String {
- return BytesUtil.toHex(
- encrypt( Bytes.ofString(text) ),
- ":");
- }
-
- /**
- * Set the public key fields N (modulus) and E (public exponent)
- * from hex strings.
- **/
- public function setPublic(nHex : String, eHex:String) : Void {
- init();
- if(nHex == null || nHex.length == 0)
- throw new chx.lang.NullPointerException("nHex not set: " + nHex);
- if(eHex == null || eHex.length == 0)
- throw new chx.lang.NullPointerException("eHex not set: " + eHex);
- //try {
- var s : String = BytesUtil.cleanHexFormat(nHex);
- n = BigInteger.ofString(s, 16);
- if(n == null) throw 2;
- var ie : Null<Int> = Std.parseInt("0x" +
BytesUtil.cleanHexFormat(eHex));
- if(ie == null || ie == 0) throw 3;
- e = ie;
- //}
- //catch(e:Dynamic)
- // throw("Invalid RSA public key: " + e);
- }
-
- /**
- * Verify a signature
- *
- * @todo http://www.imc.org/ietf-openpgp/mail-archive/msg14307.html
- * @todo verify implementation
- **/
- public function verify( data : Bytes ) : Bytes {
- return doBufferDecrypt(data, doPublic, new PadPkcs1Type1(blockSize));
- }
-
-
- //////////////////////////////////////////////////
- // Private //
- //////////////////////////////////////////////////
- /**
- * Encrypts a bytes buffer
- *
- * @param src Input bytes
- * @param f Callback for encryption
- * @param pf Padding method
- **/
- private function doBufferEncrypt(src:Bytes, f : BigInteger->BigInteger,
pf : IBlockPad) : Bytes
- {
- //trace("source: " + src.toHex());
- var bs = blockSize;
- var ts : Int = bs - 11;
- #if CAFFEINE_DEBUG
- trace(">>>> Encrypting. Blocksize is "+bs + " src length:"+src.length
+ "["+src.toHex()+"]");
- #end
- var idx : Int = 0;
- var msg = new BytesBuffer();
- while(idx < src.length) {
- if(idx + ts > src.length)
- ts = src.length - idx;
- var m:BigInteger = BigInteger.ofBytes(pf.pad(src.sub(idx,ts)), true);
- var c:BigInteger = f(m);
-
- #if CAFFEINE_DEBUG
- var d = m.toBytesUnsigned();
- var e = c.toBytesUnsigned();
- trace("m (padded) len " + d.length + " "+d.toHex(":"));
- trace("c (crypted) len " + e.length + " "+e.toHex(":"));
- #end
-
- var h = c.toBytesUnsigned();
- //var
- if((h.length & 1) != 0)
- msg.addByte( 0 );
-
- #if CAFFEINE_DEBUG
- trace(">>>> crypted ("+h.length+"): " + h.toHex());
- #end
-
- msg.add(h);
- idx += ts;
- }
- return msg.getBytes();
- }
-
- private function doBufferDecrypt(src: Bytes, f : BigInteger->BigInteger,
pf : IBlockPad) : Bytes
- {
- //trace("source: " + src.toHex());
- var bs = blockSize;
- //bs *= 2; // hex string, 2 bytes per char
- var ts : Int = bs - 11;
- #if CAFFEINE_DEBUG
- trace(">>>> Decrypting. Blocksize is "+ bs + " src length:"+src.length
+ "["+src.toHex()+"]");
- #end
- var idx : Int = 0;
- var msg = new BytesBuffer();
- while(idx < src.length) {
- if(idx + bs > src.length)
- bs = src.length - idx;
- var c : BigInteger = BigInteger.ofBytes(src.sub(idx,bs), true);
- var m = f(c);
- if(m == null)
- return null;
-
- #if CAFFEINE_DEBUG
- var d = m.toBytesUnsigned();
- var e = c.toBytesUnsigned();
- trace("c (crypted) len " + e.length + " "+e.toHex(":"));
- trace("m (padded) len " + d.length + " "+d.toHex(":"));
- #end
-
- var up : Bytes = pf.unpad(m.toBytesUnsigned());
- if(up.length > ts)
- throw "block text length error";
- msg.add(up);
- idx += bs;
- }
- return msg.getBytes();
- }
-
- // Perform raw public operation on "x": return x^e (mod n)
- function doPublic(x : BigInteger) : BigInteger {
- return x.modPowInt(this.e, this.n);
- }
-
- //////////////////////////////////////////////////
- // getters/setters //
- //////////////////////////////////////////////////
- function __getBlockSize() : Int {
- if(n == null)
- return 0;
- return (n.bitLength()+7)>>3;
- }
-
- //////////////////////////////////////////////////
- // Convenience //
- //////////////////////////////////////////////////
-
-
- public function toString() {
- return "rsa";
- /*
- var sb = new StringBuf();
- sb.add("Public:\n");
- sb.add("N:\t" + n.toHex() + "\n");
- sb.add("E:\t" + BigInteger.ofInt(e).toHex() + "\n");
- return sb.toString();
- */
- }
-}
-
=======================================
--- /trunk/ext3/chx/crypt/cert/X509Certificate.hx Wed Jan 11 12:21:57 2012
+++ /trunk/ext3/chx/crypt/cert/X509Certificate.hx Mon Feb 20 10:13:32 2012
@@ -31,6 +31,7 @@

package chx.crypt.cert;

+import chx.Lib;
import chx.collections.AssociativeArray;
import chx.hash.IHash;
import chx.hash.Md2;
@@ -53,13 +54,28 @@

/**
* X509Certificate
- *
+ * Some openssl functions to work with cert files
+ * <code>
+ * //read PEM encoded
+ * openssl x509 -in cert.pem -text -noout
+ * //read DER encoded
+ * openssl x509 -in certificate.der -inform der -text -noout
+ * // PEM to DER
+ * openssl x509 -in cert.crt -outform der -out cert.der
+ * // DER to PEM
+ * openssl x509 -in cert.crt -inform der -outform pem -out cert.pem
+ * // connect to a webserver and dump its cert
+ * openssl s_client -connect localhost:4443 -showcerts
+ * </code>
**/
class X509Certificate {

private var _loaded:Bool;
private var _param:Dynamic;
private var _obj:chx.collections.AssociativeArray<IAsn1Type>;
+ #if (neko || useOpenSSL)
+ private var handle : Dynamic;
+ #end

public function new(p:Dynamic) {
_loaded = false;
@@ -141,9 +157,7 @@
}
var data:Bytes = cast(_obj.get("signedCertificate_bin"),
ExtractedBytes).toDER();
var bs : Bytes = cast _obj.get("encrypted");
- var rv = key.verify(bs);//.toHex());
- var buf:Bytes = rv;// = Byte.ofString(rv);
- //buf.position=0;
+ var buf:Bytes = key.verify(bs);
data = fHash.calculate(data);
var obj:AssociativeArray<IAsn1Type> = cast DER.read(buf,
Types.RSA_SIGNATURE);
if (untyped obj.get("algorithm").get("algorithmId").toString() != oid) {
@@ -216,8 +230,12 @@
*/
public function getSubjectPrincipal():String {
load();
+ #if useOpenSSL
+ return
Base64.encode(Lib.nekoStringToHaxe(x509_get_subject_hash(handle)));
+ #else
var eb:ExtractedBytes = cast untyped
_obj.get("signedCertificate").get("subject_bin");
return Base64.encode(eb.toDER());
+ #end
}

/**
@@ -230,35 +248,136 @@
*/
public function getIssuerPrincipal():String {
load();
+ #if useOpenSSL
+ return Base64.encode(Lib.nekoStringToHaxe(x509_get_issuer_hash(handle)));
+ #else
var eb:ExtractedBytes = cast untyped
_obj.get("signedCertificate").get("issuer_bin");
return Base64.encode(eb.toDER());
+ #end
}

public function getAlgorithmIdentifier():String {
load();
+ #if useOpenSSL
+ var o : Dynamic = x509_get_signature_algorithm(handle);
+ if(o.der != null) {
+ o.der = DER.read(Bytes.ofData(o.der));
+ var oid : chx.formats.der.ObjectIdentifier = cast o.der;
+ return oid.toString();
+ }
+ return throw "unknown";
+ #else
return untyped
_obj.get("algorithmIdentifier").get("algorithmId").toString();
+ #end
}

/**
- Returns the starting date for a cert.
- **/
+ * Return the fingerprint
+ * @param hash Either md5 or sha1
+ **/
+ public function getFingerprint(hash:String):Bytes {
+ load();
+ #if useOpenSSL
+ return Bytes.ofData(x509_get_fingerprint(handle,hash));
+ #else
+ var b : Bytes = (Std.is(_param, String)) ? PEM.readCertIntoBytes(cast
_param) :_param;
+ if(hash == "md5") {
+ return chx.hash.Md5.encode(b);
+ }
+ return(chx.hash.Sha1.encode(b));
+ #end
+ }
+
+ /**
+ * Get the subject email addresses associated with the cert. Normally
+ * there is only one.
+ * @return Array<String> email addresses
+ **/
+ public function getEmails():Array<String> {
+ load();
+ #if useOpenSSL
+ var a : Array<String> = x509_get_emails(handle);
+ if(a == null)
+ return [];
+ for(x in 0...a.length)
+ a[x] = Lib.nekoStringToHaxe(a[x]);
+ return a;
+ #else
+ var seq :Sequence = cast untyped
_obj.get("signedCertificate").get("subject");
+ var s = seq.findAttributeValues(OID.EMAIL_ADDRESS);
+ var em : Array<String> = new Array();
+ for(i in 0...s.length) {
+ em.push(s[i].toString());
+ }
+ return em;
+ #end
+ }
+
+ /**
+ * Returns the starting date for a cert.
+ * @TODO Dates are not exact, since haxe will not parse full timezone
dates
+ **/
public function getNotBefore():Date {
load();
- var d : UTCTime = cast untyped
_obj.get("signedCertificate").get("validity").get("notBefore").get("date");
+ #if useOpenSSL
+ var dstr : String = Lib.nekoStringToHaxe(x509_get_not_before(handle));
+ return sslDateToHaxe(dstr);
+ #else
+ var d : UTCTime = cast untyped
_obj.get("signedCertificate").get("validity").get("notBefore");
return d.getDate();
+ #end
}

/**
- Returns the expiry date of a cert.
- **/
+ * Returns the expiry date of a cert.
+ * @todo see getNotBefore()
+ **/
public function getNotAfter():Date {
load();
- var d : UTCTime = cast untyped
_obj.get("signedCertificate").get("validity").get("notAfter").get("date");
+ #if useOpenSSL
+ var dstr = Lib.nekoStringToHaxe(x509_get_not_after(handle));
+ return sslDateToHaxe(dstr);
+ #else
+ var d : UTCTime = cast untyped
_obj.get("signedCertificate").get("validity").get("notAfter");
return d.getDate();
- }
+ #end
+ }
+
+ #if useOpenSSL
+ private function sslDateToHaxe(s:String) : Date {
+ //trace(s); // Mar 5 09:32:14 2013 GMT
+ var r = ~/([A-Z]{3,})[ ]+([0-9]+)[ ]+([0-9]{2}:[0-9]{2}:[0-9]{2})[
]+([0-9]{4})[ ]+([A-Z]{3,})$/i;
+ if(r.match(s)) {
+ var months = DateTools.MONTHS_ABBREV;
+ var m = r.matched(1);
+ var d = r.matched(2);
+ if(d.length == 1) d = "0" + d;
+ var t = r.matched(3);
+ var y = r.matched(4);
+
+ var p = Lambda.indexOf(months, m);
+ if(p < 0)
+ throw "Bad month " + m;
+ p++;
+ var ms = Std.string(p);
+ if(ms.length == 1)
+ ms = "0" + ms;
+ s = y + "-" + ms + "-" + d + " " + t;
+
+ }
+ //YYYY-MM-DD hh:mm:ss
+ return Date.fromString(s);
+ }
+ #end

public function getCommonName():String {
load();
+ #if useOpenSSL
+ var rv = Lib.nekoStringToHaxe(x509_get_subject(handle));
+ trace(rv);
+ // xxx
+ return "FIXME";
+ #else
var subject:Sequence = cast untyped
_obj.get("signedCertificate").get("subject");
if(subject == null) throw "No subject";
var ps : PrintableString = null;
@@ -268,6 +387,7 @@
if(ps == null)
return null;
return ps.getString();
+ #end
}

////////////////////////////////////////////////////////
@@ -275,6 +395,16 @@
////////////////////////////////////////////////////////
private function load():Void {
if (_loaded) return;
+ #if useOpenSSL
+ handle = x509_from_bytes(_param);
+ Assert.isNotNull(handle);
+ /*
+ var o = x509_parse(handle,true);
+ //Assert.isNotNull(o);
+ trace(Std.string(o));
+ throw "Ok?";
+ */
+ #else
var b:Bytes = null;
if (Std.is(_param, String))
b = PEM.readCertIntoBytes(cast _param);
@@ -291,5 +421,24 @@
else {
throw "Invalid x509 Certificate parameter: "+_param;
}
- }
-}
+ #end
+ }
+
+ static function __init__() {
+ #if useOpenSSL
+ Lib.initDll("openssl");
+ #end
+ }
+
+ #if (neko || useOpenSSL)
+ private static var
x509_from_bytes=Lib.load("openssl","x509_from_bytes",1);
+ private static var x509_parse=Lib.load("openssl","x509_parse",2);
+
+ private static var
x509_get_emails=Lib.load("openssl","x509_get_emails",1);
+ private static var
x509_get_fingerprint=Lib.load("openssl","x509_get_fingerprint",2);
+ private static var
x509_get_not_before=Lib.load("openssl","x509_get_not_before",1);
+ private static var
x509_get_not_after=Lib.load("openssl","x509_get_not_after",1);
+ private static var
x509_get_subject=Lib.load("openssl","x509_get_subject",1);
+ private static var
x509_get_signature_algorithm=Lib.load("openssl","x509_get_signature_algorithm",1);
+ #end
+}

Reply all
Reply to author
Forward
0 new messages