When you are first time to configure your cisco device(router, switch and firewall), you need a console cable to connect to its console port, and attach the other end to PC serial port, then use HyperTerminal (on Windows).
What if it is a virtual appliance on ESXi? With the new type of virtual serial port "Connect over Network", the job becomes easy. Please read this link for the details.
Saturday, 20 July 2013
Thursday, 11 July 2013
SAML Authentication on F5 Big-IP (Part 4)
The battle goes on.
F5 Product Development/Engineering Services came back with following response:
Some research with "Apache Santuario" was done.
We tried the tool which came with install "c14n" "tool to dump a XML file to the console after canonacalising it through c14n"
We checked different options and found the following:
c14n -n -x assertion.xml => This generates the canonicalized xml which is exactly same as what F5 generates.
c14n -n -x -1.1 assertion.xml => This generates what is explained in the BUG which is different from what F5 generated.
In the above command "1.1" refers to "Use c14n 1.1".
From the source code xml-security-c-1.7.1/xsec/dsig/DSIGConstants.hpp
#define URI_ID_C14N11_NOC "http://www.w3.org/2006/12/xml-c14n11"
#define URI_ID_EXC_C14N_NOC "http://www.w3.org/2001/10/xml-exc-c14n#"
This tells us that the canonicalization used by Apache Santuario is 'URI_ID_C14N11_NOC' but we see the inside SAML response which is not right.
Look at "http://www.w3.org/TR/DSig-usage/"
The solution to this problem is that, do not use "1.1" option with c14n when SAML response is generated to work with F5.
Basically, they doubted I was using C14N 1.1.
I can't find the authority in this field to get the verdict on this dispute, so I have to dive deeply into C14N, hopefully in the end I can convince F5 guys in theory where and why they were wrong.
After spending a whole week on trying to understand C14N in XML signature validation, I can confirm F5 PD/EC opinion was wrong.
Basically, the CanonicalizationMethod (in my case which is "http://www.w3.org/2001/10/xml-exc-c14n#" ) defined in SignedInfo should be ONLY used on the second step of core validation - Signature Validation.
However, F5 also employed the same method (the exclusive one) onto the first step (Reference Validation), which is wrong.
You can check my research details at this link.
F5 Product Development/Engineering Services came back with following response:
Some research with "Apache Santuario" was done.
We tried the tool which came with install "c14n" "tool to dump a XML file to the console after canonacalising it through c14n"
We checked different options and found the following:
c14n -n -x assertion.xml => This generates the canonicalized xml which is exactly same as what F5 generates.
c14n -n -x -1.1 assertion.xml => This generates what is explained in the BUG which is different from what F5 generated.
In the above command "1.1" refers to "Use c14n 1.1".
From the source code xml-security-c-1.7.1/xsec/dsig/DSIGConstants.hpp
#define URI_ID_C14N11_NOC "http://www.w3.org/2006/12/xml-c14n11"
#define URI_ID_EXC_C14N_NOC "http://www.w3.org/2001/10/xml-exc-c14n#"
This tells us that the canonicalization used by Apache Santuario is 'URI_ID_C14N11_NOC' but we see the
Look at "http://www.w3.org/TR/DSig-usage/"
The solution to this problem is that, do not use "1.1" option with c14n when SAML response is generated to work with F5.
Basically, they doubted I was using C14N 1.1.
I can't find the authority in this field to get the verdict on this dispute, so I have to dive deeply into C14N, hopefully in the end I can convince F5 guys in theory where and why they were wrong.
After spending a whole week on trying to understand C14N in XML signature validation, I can confirm F5 PD/EC opinion was wrong.
Basically, the CanonicalizationMethod (in my case which is "http://www.w3.org/2001/10/xml-exc-c14n#" ) defined in SignedInfo should be ONLY used on the second step of core validation - Signature Validation.
However, F5 also employed the same method (the exclusive one) onto the first step (Reference Validation), which is wrong.
You can check my research details at this link.
Sunday, 26 May 2013
SAML Authentication on F5 Big-IP (Part 3)
I told F5 support team, if I got time, I would give them more evidence. This UK bank holiday gave me the chance.
I believe the SHA1 algorithm has no problem in F5 implementation, so I guess, for the same SAML response, F5 must have a different canonicalization result from Apache Santuario.
In Part 2, we see how the reference validation is done. In Apache Santuario, actually we can dump the canonicalization xml content which the reference hash is computed on.
Now, let us see if we can get the same thing on F5. After some assembly code analysis on F5, I think the hash is implemented in apd (Access Policy Daemon) around 0x0825C498.
Luckily I can do the remote debug of this process.
Luckily I managed to get the canonicalization xml content on F5. You can see the details from "Collecting the Canonicalization XML content on F5".
Now the truth is out.
xmlns:ds="http://www.w3.org/2000/09/xmldsig#"
xmlns:saml="urn:oasis:names:tc:SAML:2.0:assertion"
xmlns:saml="urn:oasis:names:tc:SAML:2.0:assertion"
I am not an expert on C14N (Canonical XML), but I am inclined to believe Apache is doing right - you should not remove the attributes which exist in the original xml, you should not coin an attribute which does not exist in the original xml.
For anyone who is interested in XML signature and who would like to prove that I am right(or wrong), here they are the files.
SAML response (txt)
SAML response (xml, decoded)
XML canonical by Apache
XML canonical by F5
I believe the SHA1 algorithm has no problem in F5 implementation, so I guess, for the same SAML response, F5 must have a different canonicalization result from Apache Santuario.
In Part 2, we see how the reference validation is done. In Apache Santuario, actually we can dump the canonicalization xml content which the reference hash is computed on.
Now, let us see if we can get the same thing on F5. After some assembly code analysis on F5, I think the hash is implemented in apd (Access Policy Daemon) around 0x0825C498.
Luckily I can do the remote debug of this process.
Luckily I managed to get the canonicalization xml content on F5. You can see the details from "Collecting the Canonicalization XML content on F5".
Now the truth is out.
- On element samlp:Response, the canonicalization xml content by F5 missed two attributes
xmlns:ds="http://www.w3.org/2000/09/xmldsig#"
xmlns:saml="urn:oasis:names:tc:SAML:2.0:assertion"
- On element saml:Assertion, F5 coined an attribute
xmlns:saml="urn:oasis:names:tc:SAML:2.0:assertion"
I am not an expert on C14N (Canonical XML), but I am inclined to believe Apache is doing right - you should not remove the attributes which exist in the original xml, you should not coin an attribute which does not exist in the original xml.
For anyone who is interested in XML signature and who would like to prove that I am right(or wrong), here they are the files.
SAML response (txt)
SAML response (xml, decoded)
XML canonical by Apache
XML canonical by F5
Tuesday, 21 May 2013
SAML Authentication on F5 Big-IP (Part 2)
I knew this question was too hard for F5 support team, so in my first email I said
If it is not a known issue on VE BIGIP-11.3.0.2806.0, can you please ask your technical team to have a look?
I also knew there was no fast track for me to the right person in F5, the only thing I could do was WAIT and PROVIDE any data which they thought was necessary.
In the beginning, they doubted that the idp certificate registered on F5 Big-IP (by importing IDP metadata) was not right. I told them the SAML response contained a X509 certificate which was enough to verify the signature, but I agreed to check the idp certificate, actually it was identical to the X509 certificate.
Finally I got the feedback from their Engineering Service 47 days later. Typical bureaucratic in any big company I am afraid.
The feedback says,
------
Product Development has provided the way SAML Digest value is calculated by APM;
Note: the data with Response ID _ec3a47ec7dd9e6836d3458bec3124c61b49d89fd was collected on 2013-04-17. It is different from the one I am going to test.
Sounds like they are not yet convinced by my research described in Part 1. They may also question me back - how can I myself prove that my research in Part 1 did the verification on Reference(s)?
The SAML module on F5 Big-IP was developed with C (or C++, I believe), so this time I am going to use Apache Santuario C++ distribution.
I downloaded Apache XML Security for C++ 1.7.0 source code onto Ubuntu 12.04, then followed its installation instruction, untar, configure, make, make install etc.
The package has a tool called "checksig", After building the package, we can make use of the tool straight away.
mike@ubuntu:/opt/bin$ ./checksig ~/saml02.xml
Signature verified OK!
If it is not a known issue on VE BIGIP-11.3.0.2806.0, can you please ask your technical team to have a look?
I also knew there was no fast track for me to the right person in F5, the only thing I could do was WAIT and PROVIDE any data which they thought was necessary.
In the beginning, they doubted that the idp certificate registered on F5 Big-IP (by importing IDP metadata) was not right. I told them the SAML response contained a X509 certificate which was enough to verify the signature, but I agreed to check the idp certificate, actually it was identical to the X509 certificate.
Finally I got the feedback from their Engineering Service 47 days later. Typical bureaucratic in any big company I am afraid.
The feedback says,
------
Product Development has provided the way SAML Digest value is calculated by APM;
- if reference URI in the signature element matches the
Response ID, then digest is calculated for the entire SAML response (signature
must be within response),
- if reference URI matches Assertion ID, digest is
calculated for the Assertion element only (signature must be within assertion),
- entire signature element is removed from
response/assertion,
- resulting XML is canonicalized,
- SHA1 digest is calculated for the canonicalized XML,
- the Digest value from signature element is base64
decoded and compared to calculated digest.
In your case,the "reference URI" in signature
element matches the Response ID
"_ec3a47ec7dd9e6836d3458bec3124c61b49d89fd", so the digest is
calculated for the entire SAML response.
------Note: the data with Response ID _ec3a47ec7dd9e6836d3458bec3124c61b49d89fd was collected on 2013-04-17. It is different from the one I am going to test.
Sounds like they are not yet convinced by my research described in Part 1. They may also question me back - how can I myself prove that my research in Part 1 did the verification on Reference(s)?
The SAML module on F5 Big-IP was developed with C (or C++, I believe), so this time I am going to use Apache Santuario C++ distribution.
I downloaded Apache XML Security for C++ 1.7.0 source code onto Ubuntu 12.04, then followed its installation instruction, untar, configure, make, make install etc.
The package has a tool called "checksig", After building the package, we can make use of the tool straight away.
mike@ubuntu:/opt/bin$ ./checksig ~/saml02.xml
Signature verified OK!
Again, no complaint for digest value mismatch.
Now let check its source code. In checksig.cpp, around line 503, it has
Now let check its source code. In checksig.cpp, around line 503, it has
if (skipRefs)
result = sig->verifySignatureOnly();
else
result = sig->verify();
Note I didn't add the option --skiprefs, which implied it verified the References as well.
Now, let us check sig->verify(), the source code is in DSIGSignature.cpp, line 1151
// First thing to do is check the references
referenceCheckResult = mp_signedInfo ->verify(m_errStr);
Let us step into this function DSIGSignedInfo::verify, we get the function SIGReference::verifyReferenceList in DSIGReference.cpp. On line 920, we have
if (!r->checkHash()) {
Step into once more, we get DSIGReference::checkHash() .
Now let us debug it with gdb, set a breakpoint on this function
(gdb) break DSIGReference::checkHash
Then run it, the program break at this point. go 3 steps with n3. Now let check the values in buffer calculatedHashVal and readHashVal.
(gdb) x/20bx calculatedHashVal
0xbfffc39c: 0xc0 0x35 0xd4 0xef 0x92 0x98 0xe3 0xfc
0xbfffc3a4: 0xbb 0x27 0xbd 0x5c 0x9d 0xa2 0xeb 0xfd
0xbfffc3ac: 0xb1 0x7d 0xa0 0x30
(gdb) x/20bx readHashVal
0xbfffc41c: 0xc0 0x35 0xd4 0xef 0x92 0x98 0xe3 0xfc
0xbfffc424: 0xbb 0x27 0xbd 0x5c 0x9d 0xa2 0xeb 0xfd
0xbfffc42c: 0xb1 0x7d 0xa0 0x30
They are identical! OK, now let's check the DigestValue
wDXU75KY4/y7J71cnaLr/bF9oDA=
After doing Base64 decode, we have
c0 35 d4 ef 92 98 e3 fc bb 27 bd 5c 9d a2 eb fd b1 7d a0 30
Still have a question? I know you may want to know the actual XML content where the hash is calculated on. OK, no problem. The hash is done in TXFMSHA1.cpp, line 131,
while ((size = input->readBytes((XMLByte *) buffer, 1024)) != 0) {
#if 0
// Some useful debbugging code
FILE * f = fopen("debug.out","a+b");
fwrite(buffer, size, 1, f);
fclose(f);
#endif
mp_h->hash(buffer, size);
}
We can dump the buffer to a file (I did it by gdb append command). You can see the content in hashon.xml. This is the canonicalized XML.
Now I wonder if F5 Big-IP has the same handling on XML signature.
Now I wonder if F5 Big-IP has the same handling on XML signature.
Sunday, 19 May 2013
The Asymmetric Key of RFC 6030 (PSKC)
RFC 6030 has a sample (Figure 8) which is encrypted with PKI public key, but it doesn't say where we can get the another half part - its private key.
If you are also looking for the private key, here it is PSKC PKI certificate which I got from OATH insider. The password to the certificate is “securepass”. There is only one key in the file with alias “pskc-test-key”. The SHA1 fingerprint is,
47:0B:A5:A7:79:C7:F3:94:8A:69:28:A6:5E:84:65:C4:A1:44:7A:AC
For you convenience, here is the piece of JAVA code I use to decode the PKI encrypted token.
public void DecodeTokenWithPKI(String txtCiphered)
{
try {
KeyStore ks = KeyStore.getInstance("JKS");
FileInputStream fis = new FileInputStream("c:\\work\\pskc\\pskctest.jks");
ks.load(fis, "securepass".toCharArray()); // There are other ways to read the password.
fis.close();
Enumeration aliases = ks.aliases();
String alias = "";
while (aliases.hasMoreElements())
{
alias = aliases.nextElement();
System.out.println("alias : "+alias);
break;
}
if(alias.equals(""))
return;
// X509Certificate cert = (X509Certificate) ks.getCertificate(alias);
// RSAPublicKey pubkey = (RSAPublicKey) cert.getPublicKey();
RSAPrivateKey priv= (RSAPrivateKey) ks.getKey(alias, "securepass".toCharArray());
Base64 b64 = new Base64();
byte[] ciphertextBytes = b64.decode(txtCiphered);
AsymmetricBlockCipher theEngine = new RSAEngine();
theEngine = new PKCS1Encoding(theEngine);
RSAKeyParameters rsakeyparameters2 = new RSAKeyParameters(true, priv.getModulus(), priv.getPrivateExponent());
theEngine.init(false, rsakeyparameters2);
byte[] orgtextBytes = theEngine.processBlock(ciphertextBytes, 0, ciphertextBytes.length);
/*
Cipher cipher = Cipher.getInstance( "RSA/ECB/PKCS1Padding" );
cipher.init( Cipher.DECRYPT_MODE, priv );
byte[] orgtextBytes = cipher.doFinal( ciphertextBytes, 0, ciphertextBytes.length );
*/
System.out.println("orgy:\n" + Base64.encodeBase64String(orgtextBytes) + "\n");
} catch (Exception e) {
e.printStackTrace();
msgLastError = e.toString();
}
}
Friday, 11 January 2013
customize android ant build
The command ant release generally creates a package name with the format ${ant.project.name}-release.apk. It is quite helpful if we can add the version number and build date into the package name.
You can achieve it by writing custom_rules.xml without touching the ant build.xml file in the folder Android SDK/tools/ant.
Method 1
<?xml version="1.0" encoding="UTF-8"?>
<project name="custom_rules">
<tstamp>
<format property="today" pattern="yyyyMMdd" />
</tstamp>
<target name="override-out">
<xpath input="AndroidManifest.xml" expression="/manifest/@android:versionName"
output="manifest.versionName" default="unknown" />
<property name="out.final.file"
location="${out.absolute.dir}/${ant.project.name}-v${manifest.versionName}_${today}.apk" />
</target>
<target name="andmob" depends="override-out, clean, release" />
</project>
Method 2
<?xml version="1.0" encoding="UTF-8"?>
<project name="custom_rules">
<tstamp>
<format property="today" pattern="yyyyMMdd" />
</tstamp>
<xmlproperty file="AndroidManifest.xml" prefix="mymanifest" collapseAttributes="true"/>
<target name="-post-build">
<move file="${out.final.file}" tofile="${out.absolute.dir}/${ant.project.name}_v${mymanifest.manifest.android:versionName}_${today}.apk"/>
<echo>Rename the built package name to ${out.absolute.dir}/${ant.project.name}_v${mymanifest.manifest.android:versionName}_${today}.apk</echo>
</target>
</project>
With Method 1, you execute the command ant andmob(which we define this particular target in my example) instead of ant release. In Method 2, we add a rename(move) command in -post-build target, so you can still use the original command ant release.
Assume my project name is "andmob", current version 5.4, the build date 2013/01/11, then the final package name will be andmob-v5.4_20130111.apk
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 ----");
}
}
Subscribe to:
Posts (Atom)