I am studying at night graduate school.
While studying the cryptographic hash function, I found information that the speed of the SHA3 hash function is faster than the speed of the SHA2 hash function.
So, using JMH benchmarking in actual JAVA, I tried to compare the performance of SHA512/256 of SHA2 and SHAKE256 of SHA3 series, but there doesn't seem to be much difference than I thought.
The library I used and the source code I wrote are as follows.
SHA512-256
import java.security.MessageDigest;
public static byte[] digest(byte[] data) throws NoSuchAlgorithmException
{
CryptoProvider.setupIfNeeded();
java.security.MessageDigest digest = java.security.MessageDigest.getInstance("SHA512/256");
digest.update(Arrays.copyOf(data, data.length));
return digest.digest();
}
SHAKE256 (use 2 methods)
import org.bouncycastle.crypto.digests.SHAKEDigest;
public static byte[] shakeDigest(byte[] data, int returnLength) throws NoSuchAlgorithmException
{
CryptoProvider.setupIfNeeded();
SHAKEDigest digest = new SHAKEDigest(256);
byte[] hashBytes = new byte[returnLength];
digest.update(data, 0, data.length);
digest.doFinal(hashBytes, 0);
digest.reset();
return Arrays.copyOf(hashBytes, returnLength);
}
import com.github.aelstad.keccakj.fips202.Shake256;
public static byte[] shakeDigest2(byte[] data, int returnLength) throws Exception
{
CryptoProvider.setupIfNeeded();
Shake256 digest = new Shake256();
digest.getAbsorbStream().write(data);
byte[] hashBytes = new byte[returnLength];
digest.getSqueezeStream().read(hashBytes);
digest.reset();
return Arrays.copyOf(hashBytes, returnLength);
}
I'm wondering if I'm missing something, or if there exists a SHAKE256 library that's closer to perfection than the one I used.
Please help.
Thank you.
I generate a 128-bit AES object using "C_CreateObject".
I then do the following to encrypt a piece of data and get a "Bad Argumnents" error on the call to "C_Encrypt" to get the encrypted data length.
char clear[] = "My name is Eric!";
buf_len = sizeof(clear) -1;
rv = pfunc11->C_EncryptInit(session, pMechanism, hObject);
if (rv != CKR_OK)
{
printf("ERROR: rv=0x%08X: initializing encryption:\n", (unsigned int)rv);
return false;
}
rv = pfunc11->C_Encrypt(session, (CK_BYTE_PTR)clear, (CK_ULONG)buf_len, NULL, pulEncryptedDataLen);
if (rv != CKR_OK)
{
printf("ERROR: rv=0x%08X: derror getting encryption data buffer length:\n", (unsigned int)rv);
return false;
}
What am I doing wrong here ?
Here is my mechanism definition -
CK_MECHANISM myMechanism = {CKM_AES_CBC_PAD, (CK_VOID_PTR)"01020304050607081122334455667788", (CK_ULONG)16};
CK_MECHANISM_PTR pMechanism = &myMechanism;
Your pulEncryptedDataLen is probably NULL which causes CKR_ARGUMENTS_BAD.
It is better to use e.g.:
CK_ULONG ulEncryptedDataLen;
...
rv = pfunc11->C_Encrypt(session, (CK_BYTE_PTR)clear, (CK_ULONG)buf_len, NULL, &ulEncryptedDataLen);
The number of bytes sufficient to store encryption result of a single-part encryption gets stored into ulEncryptedDataLen.
Also please note that your way of passing IV value is not correct as "01020304050607081122334455667788" results in an ASCII string (giving IV as 30313032303330343035303630373038 -- which is probably not what you want).
To get correct IV use "\x01\x02\x03\x04\x05\x06\x07\x08\x11\x22\x33\x44\x55\x66\x77\x88" instead.
Good luck!
Is Sha256Hash from Apache Shiro based upon a common specification like PBKDF2WithHmacSHA256?
The following example proves, Shiros Sha256Hash doesn't create a valid PBKDF2WithHmacSHA256 hashes.
public static byte[] getEncryptedPassword(
String password,
byte[] salt,
int iterations,
int derivedKeyLength
) throws NoSuchAlgorithmException, InvalidKeySpecException {
KeySpec keySpec = new PBEKeySpec(
password.toCharArray(),
salt,
iterations,
derivedKeyLength * 8
);
SecretKeyFactory f = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA256");
return f.generateSecret(keySpec).getEncoded();
}
#Test
public void testHashing(){
byte[] salt = new SecureRandomNumberGenerator().nextBytes().getBytes();
byte[] hash1 = new Sha256Hash("1234", salt, 1024).getBytes();
byte[] hash2 = getEncryptedPassword("1234", salt, 1024, 32);
assertTrue(hash1.equals(hash2));
}
Is there a common way to use PBKDF2WithHmacSHA256 with shiro, or do I have to implement my own CredentialMatcher?
Per the Shiro user list on nabble no, Shiro does not provide PBKDF2 (or BCrypt or SCrypt).
Note that Java 8 does have PBKDF2-HMAC-SHA-512 available now as PBKDF2WithHmacSHA512 - use that instead. SHA-512 in particular has 64-bit operations that reduce the advantage GPU based attackers have. Use more iterations than just 1024, as well - see what your system can handle comfortably under load!
I'm using the following code to encrypt a string using md5
const char* str = [#"123456" UTF8String];
unsigned char result[CC_MD5_DIGEST_LENGTH];
CC_MD5(str, strlen(str), result);
NSMutableString *ret = [NSMutableString stringWithCapacity:CC_MD5_DIGEST_LENGTH*2];
for(int i = 0; i<CC_MD5_DIGEST_LENGTH; i++) {
[ret appendFormat:#"%02x",result[i]];
}
NSLog(#"%#", ret);
now I want a source code to decrypt the coded string, Any Help?
You can't decrypt an MD5 HASH, it is a oneway encryption.
MD5 is not an Encryption.
It is a hash function.
Finding the original value from a hash function is in general not possible.
I have a certificate (SecCertificateRef), I can check if it's valid and I can extract a "summary" using SecCertificateCopySubjectSummary.
What is the "summary" exactly? I don't understand the term "A string that contains a human-readable summary of the contents of the certificate." in the Apple documentation. I think, they mean the "CN" in the certificate, correct?
Is there any method to get the clear X509-information out of SecCertificateRef? Does a cast to a keychain-object help?
I want to have something like this and I am especially focussed on the "CN" to compare it with the URL I submitted to avoid man-in-the-middle attacks. (Or any better ideas?)
That is what I want to have:
Version: 3 (0x2)
Serial Number: 1 (0x1)
Signature Algorithm: md5WithRSAEncryption
Issuer: C=XY, ST=Austria, L=Graz, O=TrustMe Ltd, OU=Certificate Authority, CN=CA/Email=ca#trustme.dom
Validity
Not Before: Oct 29 17:39:10 2000 GMT
Not After : Oct 29 17:39:10 2001 GMT
Subject: C=DE, ST=Austria, L=Vienna, O=Home, OU=Web Lab, CN=anywhere.com/Email=xyz#anywhere.com
Subject Public Key Info:
Public Key Algorithm: rsaEncryption
RSA Public Key: (1024 bit)
Modulus (1024 bit):
00:c4:40:4c:6e:14:1b:61:36:84:24:b2:61:c0:b5:
d7:e4:7a:a5:4b:94:ef:d9:5e:43:7f:c1:64:80:fd:
9f:50:41:6b:70:73:80:48:90:f3:58:bf:f0:4c:b9:
90:32:81:59:18:16:3f:19:f4:5f:11:68:36:85:f6:
1c:a9:af:fa:a9:a8:7b:44:85:79:b5:f1:20:d3:25:
7d:1c:de:68:15:0c:b6:bc:59:46:0a:d8:99:4e:07:
50:0a:5d:83:61:d4:db:c9:7d:c3:2e:eb:0a:8f:62:
8f:7e:00:e1:37:67:3f:36:d5:04:38:44:44:77:e9:
f0:b4:95:f5:f9:34:9f:f8:43
Exponent: 65537 (0x10001)
X509v3 extensions:
X509v3 Subject Alternative Name:
email:xyz#anywhere.com
Netscape Comment:
mod_ssl generated test server certificate
Netscape Cert Type:
SSL Server
Signature Algorithm: md5WithRSAEncryption
12:ed:f7:b3:5e:a0:93:3f:a0:1d:60:cb:47:19:7d:15:59:9b:
3b:2c:a8:a3:6a:03:43:d0:85:d3:86:86:2f:e3:aa:79:39:e7:
82:20:ed:f4:11:85:a3:41:5e:5c:8d:36:a2:71:b6:6a:08:f9:
cc:1e:da:c4:78:05:75:8f:9b:10:f0:15:f0:9e:67:a0:4e:a1:
4d:3f:16:4c:9b:19:56:6a:f2:af:89:54:52:4a:06:34:42:0d:
d5:40:25:6b:b0:c0:a2:03:18:cd:d1:07:20:b6:e5:c5:1e:21:
44:e7:c5:09:d2:d5:94:9d:6c:13:07:2f:3b:7c:4c:64:90:bf:
ff:8e
I couldn't wait for an answer to the bounty, so I found a solution myself. As others said, Security.framework doesn't give you a way to get this information, so you need to ask OpenSSL to parse the certificate data for you:
#import <openssl/x509.h>
// ...
NSData *certificateData = (NSData *) SecCertificateCopyData(certificate);
const unsigned char *certificateDataBytes = (const unsigned char *)[certificateData bytes];
X509 *certificateX509 = d2i_X509(NULL, &certificateDataBytes, [certificateData length]);
NSString *issuer = CertificateGetIssuerName(certificateX509);
NSDate *expiryDate = CertificateGetExpiryDate(certificateX509);
Where CertificateGetIssuerName and CertificateGetExpiryDate are as follows:
static NSString * CertificateGetIssuerName(X509 *certificateX509)
{
NSString *issuer = nil;
if (certificateX509 != NULL) {
X509_NAME *issuerX509Name = X509_get_issuer_name(certificateX509);
if (issuerX509Name != NULL) {
int nid = OBJ_txt2nid("O"); // organization
int index = X509_NAME_get_index_by_NID(issuerX509Name, nid, -1);
X509_NAME_ENTRY *issuerNameEntry = X509_NAME_get_entry(issuerX509Name, index);
if (issuerNameEntry) {
ASN1_STRING *issuerNameASN1 = X509_NAME_ENTRY_get_data(issuerNameEntry);
if (issuerNameASN1 != NULL) {
unsigned char *issuerName = ASN1_STRING_data(issuerNameASN1);
issuer = [NSString stringWithUTF8String:(char *)issuerName];
}
}
}
}
return issuer;
}
static NSDate *CertificateGetExpiryDate(X509 *certificateX509)
{
NSDate *expiryDate = nil;
if (certificateX509 != NULL) {
ASN1_TIME *certificateExpiryASN1 = X509_get_notAfter(certificateX509);
if (certificateExpiryASN1 != NULL) {
ASN1_GENERALIZEDTIME *certificateExpiryASN1Generalized = ASN1_TIME_to_generalizedtime(certificateExpiryASN1, NULL);
if (certificateExpiryASN1Generalized != NULL) {
unsigned char *certificateExpiryData = ASN1_STRING_data(certificateExpiryASN1Generalized);
// ASN1 generalized times look like this: "20131114230046Z"
// format: YYYYMMDDHHMMSS
// indices: 01234567890123
// 1111
// There are other formats (e.g. specifying partial seconds or
// time zones) but this is good enough for our purposes since
// we only use the date and not the time.
//
// (Source: http://www.obj-sys.com/asn1tutorial/node14.html)
NSString *expiryTimeStr = [NSString stringWithUTF8String:(char *)certificateExpiryData];
NSDateComponents *expiryDateComponents = [[NSDateComponents alloc] init];
expiryDateComponents.year = [[expiryTimeStr substringWithRange:NSMakeRange(0, 4)] intValue];
expiryDateComponents.month = [[expiryTimeStr substringWithRange:NSMakeRange(4, 2)] intValue];
expiryDateComponents.day = [[expiryTimeStr substringWithRange:NSMakeRange(6, 2)] intValue];
expiryDateComponents.hour = [[expiryTimeStr substringWithRange:NSMakeRange(8, 2)] intValue];
expiryDateComponents.minute = [[expiryTimeStr substringWithRange:NSMakeRange(10, 2)] intValue];
expiryDateComponents.second = [[expiryTimeStr substringWithRange:NSMakeRange(12, 2)] intValue];
NSCalendar *calendar = [NSCalendar currentCalendar];
expiryDate = [calendar dateFromComponents:expiryDateComponents];
[expiryDateComponents release];
}
}
}
return expiryDate;
}
I only actually needed the issuer's organization name and the expiry date for my purposes, so that's all the code I've included below. But, based on this you should be able to figure out the rest by reading the x509.h header file.
Edit:
Here's how to get the certificate. I haven't put any error handling, etc. You'll want to check trustResult, err, etc., for example.
NSURLAuthenticationChallenge *challenge;
SecTrustResultType trustResult;
SecTrustRef trust = challenge.protectionSpace.serverTrust;
OSStatus err = SecTrustEvaluate(trust, &trustResult);
SecCertificateRef certificate = SecGetLeafCertificate(trust); // See Apple docs for implementation of SecGetLeafCertificate
better just use SecCertificateCopyCommonName to get CN to compare to your required hostname.
You were right Michael, iOS won't give you the API to do a full job on a X.509 certificates. Thankfully it will give you access to the actual (ASN.1) encoded certificate data. From there you can do your own decoding (not much fun) or delegate it to an existing library, like you did with OpenSSL.
Here's my version that uses the .NET framework. It's mean to be used by MonoTouch developers (and MonoMac developers too) who needs to interoperate with SecCertificateRef within their applications.
public void Show (SecCertificate sc)
{
// get the SecCertificate "raw", i.e. ASN.1 encoded, data
byte[] data = sc.DerData.ToArray<byte> ();
// the build the managed X509Certificate2 from it
X509Certificate2 cer = new X509Certificate2 (data);
// to get all properties / methods available in .NET (pretty exhaustive)
Console.WriteLine ("SubjectName: {0}", cer.Subject);
Console.WriteLine ("IssuerName: {0}", cer.Issuer);
Console.WriteLine ("NotBefore: {0}", cer.NotBefore);
Console.WriteLine ("NotAfter: {0}", cer.NotAfter);
Console.WriteLine ("SerialNumber: {0}", cer.SerialNumber);
// ...
}
If for some reason you want to do this without OpenSSL one can use the apple extraction keys. The first one will extract (just) the Subject and Issuer (there are more kSecOIDX509's for most other things, like expiry dates) and pass them for printing.
+(NSString*)stringFromCerificateWithLongwindedDescription:(SecCertificateRef) certificateRef {
if (certificateRef == NULL)
return #"";
CFStringRef commonNameRef;
OSStatus status;
if ((status=SecCertificateCopyCommonName(certificateRef, &commonNameRef)) != errSecSuccess) {
NSLog(#"Could not extract name from cert: %#",
SecCopyErrorMessageString(status, NULL));
return #"Unreadable cert";
};
CFStringRef summaryRef = SecCertificateCopySubjectSummary(certificateRef);
if (summaryRef == NULL)
summaryRef = CFRetain(commonNameRef);
CFErrorRef error;
const void *keys[] = { kSecOIDX509V1SubjectName, kSecOIDX509V1IssuerName };
const void *labels[] = { "Subject", "Issuer" };
CFArrayRef keySelection = CFArrayCreate(NULL, keys , sizeof(keys)/sizeof(keys[0]), &kCFTypeArrayCallBacks);
CFDictionaryRef vals = SecCertificateCopyValues(certificateRef, keySelection,&error);
NSMutableString *longDesc = [[NSMutableString alloc] init];
for(int i = 0; i < sizeof(keys)/sizeof(keys[0]); i++) {
CFDictionaryRef dict = CFDictionaryGetValue(vals, keys[i]);
CFArrayRef values = CFDictionaryGetValue(dict, kSecPropertyKeyValue);
if (values == NULL)
continue;
[longDesc appendFormat:#"%s:%#\n\n", labels[i], [NSString stringFromDNwithSubjectName:values]];
}
CFRelease(vals);
CFRelease(summaryRef);
CFRelease(commonNameRef);
return longDesc;
}
The second function is an over the top try to extract anything you can get your mittens on:
+(NSString *)stringFromDNwithSubjectName:(CFArrayRef)array {
NSMutableString * out = [[NSMutableString alloc] init];
const void *keys[] = { kSecOIDCommonName, kSecOIDEmailAddress, kSecOIDOrganizationalUnitName, kSecOIDOrganizationName, kSecOIDLocalityName, kSecOIDStateProvinceName, kSecOIDCountryName };
const void *labels[] = { "CN", "E", "OU", "O", "L", "S", "C", "E" };
for(int i = 0; i < NVOID(keys); i++) {
for (CFIndex n = 0 ; n < CFArrayGetCount(array); n++) {
CFDictionaryRef dict = CFArrayGetValueAtIndex(array, n);
if (CFGetTypeID(dict) != CFDictionaryGetTypeID())
continue;
CFTypeRef dictkey = CFDictionaryGetValue(dict, kSecPropertyKeyLabel);
if (!CFEqual(dictkey, keys[i]))
continue;
CFStringRef str = (CFStringRef) CFDictionaryGetValue(dict, kSecPropertyKeyValue);
[out appendFormat:#"%s=%# ", labels[i], (__bridge NSString*)str];
}
}
return [NSString stringWithString:out];
}
I don't believe there is a public API to do this on iOS. On OSX there are a number of SecCertificate APIs to pick apart the X.509 information.
FYI, assuming you're using HTTPS, checking the CN yourself is mostly useless, because the OS already checks to make sure the name is present in the cert. You're more likely to want to check the public key (for key pinning), which you can get from the trust object without touching the certificate directly.
If the public key matches the previous key, then either the site is legit or somebody has thoroughly compromised the site.