Friday 7 December 2012

Slow creation of PKCS12(PFX) certificate

This java code works on Windows system with an acceptable speed (around 1 sec), but it takes up to 1 minute on Linux system.

After some investigation, I found it is also down to slow SecureRandom issue on Linux.

The workaround is easy, use the switch -Djava.security.egd=file:/dev/./urandom if you are using JRE 1.5+.

I did a test on CentOS(an ESXi VM), see how different the results are!

java -classpath .:bcprov.jar KeyPairCost
---- test start ----
Generate KeyPair takes 176 msec
Store takes 58923 msec
---- test end ----

java -Djava.security.egd=file:/dev/./urandom -classpath .:bcprov.jar KeyPairCost
---- test start ----
Generate KeyPair takes 297 msec
Store takes 404 msec
---- test end ----

Java Code

import java.io.ByteArrayOutputStream;
import java.util.*;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.KeyStore;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.SecureRandom;
import java.security.cert.Certificate;
import java.security.Security;

import java.math.BigInteger;
import java.security.cert.X509Certificate;

import org.bouncycastle.x509.X509V1CertificateGenerator;
import org.bouncycastle.jce.X509Principal;
import org.bouncycastle.jce.provider.BouncyCastleProvider;

public class KeyPairCost
{
    static X509V1CertificateGenerator  v1CertGen = new X509V1CertificateGenerator();

    public static void generateKeyPairCost() throws Exception
    {
        // signers name 
        String  issuer = "KeyPairCost";
        // subjects name - the same as we are self signed.
        String  subject = "KeyPairCost";
  
  java.util.Date date1 = new java.util.Date();
  
  KeyPairGenerator keyGen = KeyPairGenerator.getInstance("RSA");
  keyGen.initialize(1024); //default SecureRandom
  KeyPair keypair = keyGen.genKeyPair();
  PrivateKey privKey = keypair.getPrivate();
  PublicKey pubKey = keypair.getPublic();
  
  java.util.Date date2 = new java.util.Date();
  long diff = date2.getTime()-date1.getTime();
  System.out.println("Generate KeyPair takes " + diff + " msec");
  
        // create the certificate - version 1
  v1CertGen.setSerialNumber(BigInteger.valueOf(System.currentTimeMillis()));
        v1CertGen.setIssuerDN(new X509Principal(issuer));
        v1CertGen.setNotBefore(new Date(System.currentTimeMillis() - 1000L * 60 * 60 * 24 * 30)); // one month
        v1CertGen.setNotAfter(new Date(System.currentTimeMillis() + (1000L * 60 * 60 * 24 * 30 * 1200 ))); // 10 years
        v1CertGen.setSubjectDN(new X509Principal(subject));
        v1CertGen.setPublicKey(pubKey);
        v1CertGen.setSignatureAlgorithm("SHA1WithRSAEncryption");

        X509Certificate cert = v1CertGen.generate(privKey,"BC");

       
        
//  now write it to key store        
        KeyStore ks = KeyStore.getInstance("PKCS12");
        ks.load(null, "changeit".toCharArray());

        Certificate[] chain = new Certificate[1];
        chain[0] = cert;
        
        ks.setKeyEntry("dualidp", privKey, "changeit".toCharArray(), chain);

        ByteArrayOutputStream bOut = new ByteArrayOutputStream();

        ks.store(bOut, "changeit".toCharArray());
        
  java.util.Date date3 = new java.util.Date();
  diff = date3.getTime()-date2.getTime();
  System.out.println("Store takes " + diff + " msec");

     }
 
 
 
 public static void main(String[] args)
 {
  Security.addProvider(new BouncyCastleProvider());
  System.out.println("----  test start ----");
  try {
   generateKeyPairCost();
  } catch (Exception e) {
   e.printStackTrace();
  }
  System.out.println("----  test end ----");
 }
 
}

Friday 17 August 2012

北大力学82入学三十周年同学会

那天打开邮箱,见自力转发永爽的关于北大力学82入学三十周年聚会来信,心潮澎湃。想自己已是一个近知天命的人,世上竟然还有让我为之激动且久久不能平息的事, 略感惊讶。

回不去了,便坐下来任思绪纵横。一晃三十年,然四年的大学生活在我脑海里还是那样清晰。

我记得,是郑崗兄把我从新生接待站领到后来生活了四年的228宿舍,从此以后我对228这个数字记得最深刻。

我记得,流体力学课上,吴望一老师讲解后烟圈穿越前烟圈的流体力学原理。在北大能聆听吴老师这样大师级的人物讲课,真的是人生的一大享受。讲完后吴老师笑着问大家信服不信服? 我这个分不清鼻音的南方人在底下琢磨,吴老师问的是幸福还是信服?从生活中的一个普通事例,上升到一个无懈可击的理论,能听到这样的授课,我真的感到幸福。不过吴老师,我可是一个实践是检验真理的唯一标准的忠实信徒,之后的数年我可没有少实践哦!

我记得,大学四年,我有幸去过张健,剑为兄,还有励争姐的家打牙祭。 热情的叔叔阿姨, 让我体会了家的温暖,也使我少了几分乡愁。

我记得,毕业时我们几个留守到最后的同学去火车站送别学妹吴瑞云,那一刻我见证了什么叫依依不舍。

若要问我大学四年有什么缺憾的话,我总结有三点: 应该多往别的宿舍转一转, 多与一班三班的同学聊一聊,多去35楼窜一窜;)。

回不去了, 对我来说这注定是个遗憾。 我最遗憾自己又失去了一个机会见见毕业后再没有机会见过的228宿舍的老大哥林成功。老大哥,打你我分别以后,我再也没有吃到过正宗的 homemade 山东白薯干啊:(。

不回忆了。再回忆,伤感就来了。

明天我会将此文贴到自己的Blog。让Google与我一起铭记这一天, 17/08/2012, 欢笑与眼泪分不开的日子。

北大力学82每一位同学,我想念你。曾经教我授我的每一位老师,我想念您!

马明发,于英国 Bletchley Park

励争姐后来纠正说她们当时住30楼。对不起,我记错了,真的不是笔误。岁月不饶人啊,再过十年,恐怕要张冠李戴了,哈哈。

Monday 2 July 2012

LDAP_MATCHING_RULE_IN_CHAIN Load Test

You can use following LDAP search filter to list all the groups that a user is a member of.

member:1.2.840.113556.1.4.1941:=(cn=user1,cn=users,DC=x)

However this operation can be very expensive on the DC if you have a deep nesting structure for your groups.

You can use Apache JMeter to do LDAP load test.

Ever wonder a simpler way (without any third-party tool involved) to test the performance? Well, try MS dsquery.

First of all, get the user's DN string with the following command

dsquery user -name "john*"

Assume it returns

"CN=john smith,CN=Users,DC=ds03,DC=local"

Then execute the following command to see if the results are expected.

dsquery * domainroot -filter "(&(member:1.2.840.113556.1.4.1941:=CN=john smith,CN=Users,DC=ds03,DC=local))" -limit 10

Now, save the following as a DOS batch file, don't forget to modify it to use your own LDAP filter.

@echo off
@rem --------------------------------------------
setlocal ENABLEEXTENSIONS

set start_time=%time%
echo Beginning at: %start_time%
echo Running Timed Batch File
echo.


@rem CHANGE YOUR OWN LDAP Filter
dsquery * domainroot -filter "(&(member:1.2.840.113556.1.4.1941:=CN=john smith,CN=Users,DC=ds03,DC=local))" -limit 10


set stop_time=%time%
echo.
echo Timed Batch File Completed
echo Start time: %start_time%
echo Stop time : %stop_time%


set TEMPRESULT=%start_time:~0,2%
call:FN_REMOVELEADINGZEROS
set start_hour=%TEMPRESULT%
@rem
set TEMPRESULT=%start_time:~3,2%
call:FN_REMOVELEADINGZEROS
set start_min=%TEMPRESULT%
@rem
set TEMPRESULT=%start_time:~6,2%
call:FN_REMOVELEADINGZEROS
set start_sec=%TEMPRESULT%
@rem
set TEMPRESULT=%start_time:~9,2%
call:FN_REMOVELEADINGZEROS
set start_hundredths=%TEMPRESULT%

set TEMPRESULT=%stop_time:~0,2%
call:FN_REMOVELEADINGZEROS
set stop_hour=%TEMPRESULT%
@rem
set TEMPRESULT=%stop_time:~3,2%
call:FN_REMOVELEADINGZEROS
set stop_min=%TEMPRESULT%
@rem
set TEMPRESULT=%stop_time:~6,2%
call:FN_REMOVELEADINGZEROS
set stop_sec=%TEMPRESULT%
@rem
set TEMPRESULT=%stop_time:~9,2%
call:FN_REMOVELEADINGZEROS
set stop_hundredths=%TEMPRESULT%

set /A start_total=(((((%start_hour%*60)+%start_min%)*60)+%start_sec%)*100)+%start_hundredths%
set /A stop_total=(((((%stop_hour%*60)+%stop_min%)*60)+%stop_sec%)*100)+%stop_hundredths%

set /A total_time=%stop_total% - %start_total%

set /A total_hundredths=%total_time% %% 100
set total_hundredths=00%total_hundredths%
set total_hundredths=%total_hundredths:~-2%
set /A total_time=%total_time% / 100

set /A total_sec="%total_time% %% 60"
set total_sec=00%total_sec%
set total_sec=%total_sec:~-2%
set /A total_time=%total_time% / 60

set /A total_min="%total_time% %% 60"
set total_min=00%total_min%
set total_min=%total_min:~-2%
set /A total_time=%total_time% / 60

set /A total_hour="%total_time% %% 60"
@rem Handle if it wrapped around over midnight
if "%total_hour:~0,1%"=="-" set /A total_hour=%total_hour% + 24

echo Total time: %total_hour%:%total_min%:%total_sec%.%total_hundredths%

@rem --------------------------------------------
@rem Exit the BAT Program
endlocal
goto END

@rem --------------------------------------------
@rem FN_REMOVELEADINGZEROS function
@rem  Used to remove leading zeros from Decimal
@rem  numbers so they are not treated as Octal.
:FN_REMOVELEADINGZEROS
if "%TEMPRESULT%"=="0" goto END
if "%TEMPRESULT:~0,1%" NEQ "0" goto END
set TEMPRESULT=%TEMPRESULT:~1%
goto FN_REMOVELEADINGZEROS

@rem --------------------------------------------
@rem BAT PROGRAM / FUNCTION FILE EXIT
:END


Tuesday 12 June 2012

KVM Practice

Recently I had chance to try KVM on server4you dedicated server. The result is quiet impressive. Nowadays KVM is on a par with the commercial bare metal technoligy like ESX.

Please read this PDF version for what I have done, which includes upgrading Linux kernal, KVM, iptables firewall, VNC, VPN, SFTP, SAMBA, even NGINX.

Tuesday 17 April 2012

Configure TLS on Exchange 2010 with own certificate


In this article, I try to describe how to use the certificate signed by own CA to configure TLS on Exchange server 2010. The OpenSSL setting on crlDistributionPoints is very important, without a reachable CRL Distribution Point the certificate will not work (properly) in Exchange. Please read the PDF version for the details.

Thursday 16 February 2012

Juniper SAML and ADFS 2.0

Juniper adds SAML to SSL VPN, however I can hardly find the technical document for how to make it work with MS ADFS 2.0. Luckily I worked it out by myself. Here is the details.

Monday 16 January 2012

Yet another LDAP Benchmark

It seems this LDAP benchmark (from Novell Cool Solutions) doesn't support LDAPS, so I decided to write my own one.



You can download the project (source code). Please download and install WTL if you want to recompile it.


Note: I added a DDX DDX_COMBO_INDEX, you need to customize atlddx.h. For your convenience, I attached the modified atlddx.h in the project.

Thread Dump Beheaded

Tomcat(Windows version) Thread Dump adds some time info which makes it unloadable with Thread Dump Analyzer (like TDA). I can't figure out the settings(if any) to remove it, so I wrote a small utility - Thread Dump Beheaded, Horror? but it is true, remove the head.


The original thread dump has the following format.



[2012-01-06 11:48:57] [info] Procrun (2.0.6.0) started
[2012-01-06 11:48:57] [info] Running Service...
[2012-01-06 11:48:57] [info] Starting service...
[2012-01-06 11:49:04] [info] Service started in 6921 ms.
[2012-01-09 11:45:11] [info] Console CTRL+BREAK event signaled
[2012-01-09 11:45:11] [info] 2012-01-09 11:45:11
[2012-01-09 11:45:11] [info] Full thread dump Java HotSpot(TM) Server VM (11.2-b01 mixed mode):
[2012-01-09 11:45:11] [info]
[2012-01-09 11:45:11] [info] "http-8074-44"
[2012-01-09 11:45:11] [info] daemon
[2012-01-09 11:45:11] [info] prio=6 tid=0x6c14c800
[2012-01-09 11:45:11] [info] nid=0x1158
[2012-01-09 11:45:11] [info] in Object.wait()
[2012-01-09 11:45:11] [info] [0x715bf000..0x715bfbe8]
[2012-01-09 11:45:11] [info] java.lang.Thread.State: WAITING (on object monitor)
[2012-01-09 11:45:11] [info] at java.lang.Object.wait(Native Method)
[2012-01-09 11:45:11] [info] - waiting on <0x6296a3b0>
[2012-01-09 11:45:11] [info] (a org.apache.tomcat.util.net.JIoEndpoint$Worker)
[2012-01-09 11:45:11] [info] at java.lang.Object.wait(Object.java:485)
[2012-01-09 11:45:11] [info] at org.apache.tomcat.util.net.JIoEndpoint$Worker.await(JIoEndpoint.java:458)
[2012-01-09 11:45:11] [info] - locked <0x6296a3b0>
[2012-01-09 11:45:11] [info] (a org.apache.tomcat.util.net.JIoEndpoint$Worker)
[2012-01-09 11:45:11] [info] at org.apache.tomcat.util.net.JIoEndpoint$Worker.run(JIoEndpoint.java:484)
[2012-01-09 11:45:12] [info] at java.lang.Thread.run(Unknown Source)
[2012-01-09 11:45:12] [info]

After removing head, and organizing the line.



Procrun (2.0.6.0) started
Running Service...
Starting service...
Service started in 6921 ms.
Console CTRL+BREAK event signaled
2012-01-09 11:45:11
Full thread dump Java HotSpot(TM) Server VM (11.2-b01 mixed mode):

"http-8074-44" daemon prio=6 tid=0x6c14c800 nid=0x1158 in Object.wait() [0x715bf000..0x715bfbe8]
java.lang.Thread.State: WAITING (on object monitor)
at java.lang.Object.wait(Native Method)
- waiting on <0x6296a3b0> (a org.apache.tomcat.util.net.JIoEndpoint$Worker)
at java.lang.Object.wait(Object.java:485)
at org.apache.tomcat.util.net.JIoEndpoint$Worker.await(JIoEndpoint.java:458)
- locked <0x6296a3b0> (a org.apache.tomcat.util.net.JIoEndpoint$Worker)
at org.apache.tomcat.util.net.JIoEndpoint$Worker.run(JIoEndpoint.java:484)
at java.lang.Thread.run(Unknown Source)


This is a Windows console application, so go to Windows Prompt, execute tdbehead tdorginal.log, it will produce a file called tdorginal.bhd which now can be loaded by TDA. You can download the whole project which contains source code, binary and the thread dump sample.