Hello I'm trying to see if they're any JWT token library similar to JOSE-JWT that also works on a Linux machine during runtime.
This is what I currently have in code that decrypts a token and grabs what I need.
private IamTokenDecrypted DecryptToken(string idToken)
{
byte[] key = WebEncoders.Base64UrlDecode(_ssoEncryptionKeyInfo.JsonWebKey.K);
string json = Jose.JWT.Decode(idToken, key, JweAlgorithm.DIR, JweEncryption.A256GCM);
var result = Jose.JWT.Payload(json);
var iamTokenDecrypted = JsonConvert.DeserializeObject<IamTokenDecrypted>(result);
return iamTokenDecrypted;
}
I have a security key and and as you see it has some encryption in it
I have a RSA key which I got from a service provider. I just want to encrypt the string data with that RSA key by using the PCLCrypto library. I don't want to create the RSA key by using PCLCrypto. I only wanted to encrypt the data. (I am developing a PCL component in xamarin.)
Follow the documentation for AES encryption and modify it for RSA. Use AsymmetricAlgorithm.RsaPkcs1 as algorithm provider.
Below example is for AES.
byte[] keyMaterial;
byte[] data;
var provider = WinRTCrypto.SymmetricKeyAlgorithmProvider.OpenAlgorithm(SymmetricAlgorithm.AesCbcPkcs7);
var key = provider.CreateSymmetricKey(keyMaterial);
// The IV may be null, but supplying a random IV increases security.
// The IV is not a secret like the key is.
// You can transmit the IV (w/o encryption) alongside the ciphertext.
var iv = WinRTCrypto.CryptographicBuffer.GenerateRandom(provider.BlockLength);
byte[] cipherText = WinRTCrypto.CryptographicEngine.Encrypt(key, data, iv);
// When decrypting, use the same IV that was passed to encrypt.
byte[] plainText = WinRTCrypto.CryptographicEngine.Decrypt(key, cipherText, iv);
I have an api that returns me public key. Here is a public key sample,
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ9AMIIBCgKCAQEAoqB1N9kugk4UKYnbh0fcg3qYyYKP0m4B
MjWd05ReeAdj+7JRYDEKO6xthDdVSdRO1/2V+YtY8DnXWnxRaICwu8235s3imZCyqgYnomPWdY+F
K540oTz/zug+9wbrlzt/WQFUU4lPlQbzm/Gjw8XfaCozT0e3bnWQcD7rORCOyuJgwSGgREjTv1ss
pgEaKTMknii9vpGZLeAXwoeIYROhuT4IoIkPDhtY0/UZiCi6v7Ja2dmy53VlWIkcm3rcnSJdvpXr
OgiHvaNABHmeymNycNqd6WUaysBRheluQ86nq/2nZPW0gcvmYt5zbMMYX3yY/n2WtAKeNQBAEW1q
b0s6MwIDAQAB
Now I need to encode string a=1&b=2 using RSA algorithm,
var key = await GetPublicKey();
var keyXml = "<RSAKeyValue><Modulus>" + key + "</Modulus><Exponent>AQAB</Exponent></RSAKeyValue>";
EncrptedValue = CryptUtils.Encrypt(keyXml, "amount=1¤cy=aed", RsaKeyLengths.Bit1024);
I am using CryptUtils class at https://github.com/ServiceStack/ServiceStack/blob/master/src/ServiceStack.Common/CryptUtils.cs.
Now I am sending the encrypted value to another server but another server guy telling me that the encrypted value is not corect. What I am doing wrong?
We are tasked with determining inside our app whether or not a specific configuration profile is installed on an iOS device. There exists no public API to check which configuration profiles are installed on a device, but this article http://blog.markhorgan.com/?p=701 describes a workaround.
Basically one includes a root CA inside the configuration profile and signs with this root CA a second certificate. This second certificate gets bundled in the app and then a trust evaluation of this second certificate in the app will reveal whether or not the root CA is present (and this means that the configuration profile is installed).
Now, we are not able to tamper with our configuration profile in question (because it is installed on many devices already), but it does already include 2 certificates which we do have access to:
OurRootCA (issued by: OurRootCA)
OurIntermediateCA (issued by: OurRootCA)
unfortunately, OurRootCA is not only included in the configuration profile in question, but also in other configuration profiles (so a check with this method could yield false positives), but fortunately OurIntermediateCA is solely used in the configurationProfile we want to check for.
Unfortunately, for some reasons, the tests fails (it always returns kSecTrustResultRecoverableTrustFailure) if performed with a test SSL certificate that was issued by OurIntermediateCA (it works though with a test SSL certificate that was issued by OurRootCA).
Here's the validation code:
//NSString* certPath = [[NSBundle mainBundle] pathForResource:#"TestCertificateSignedByRoot" ofType:#"cer"]; //with this cert, the validation works
NSString* certPath = [[NSBundle mainBundle] pathForResource:#"TestCertificateSignedByIntermediate" ofType:#"cer"];
NSData* certData = [NSData dataWithContentsOfFile:certPath];
SecCertificateRef cert = SecCertificateCreateWithData(NULL, (__bridge CFDataRef) certData);
SecPolicyRef policy = SecPolicyCreateBasicX509();
SecTrustRef trust;
OSStatus err = SecTrustCreateWithCertificates((__bridge CFArrayRef) [NSArray arrayWithObject:(__bridge id)cert], policy, &trust);
// set trust anchor certificates to empty array as advised in http://stackoverflow.com/questions/7900896/sectrustevaluate-always-returns-ksectrustresultrecoverabletrustfailure-with-secp
SecTrustSetAnchorCertificates(trust, (__bridge CFArrayRef) [NSArray array]);
SecTrustSetAnchorCertificatesOnly(trust, NO);
SecTrustResultType trustResult = -1;
err = SecTrustEvaluate(trust, &trustResult);
CFRelease(trust);
CFRelease(policy);
CFRelease(cert);
switch(trustResult) {
case kSecTrustResultUnspecified:
case kSecTrustResultProceed: {
return YES;
// this is the result if TestCertificateSignedByRoot is used
break;
}
case kSecTrustResultRecoverableTrustFailure: {
return NO;
// this is the result if TestCertificateSignedByIntermediate is used
break;
}
default: {
return NO;
break;
}
}
So, the technique seems to work - the (self-signed) rootCA in the users keychain is used to validate our test certificate. But if the intermediate CA is checked for, the test always returns kSecTrustResultRecoverableTrustFailure. What could be the problem here and how can it be debugged?
While improving the security of an iOS application that we are developing, we found the need to PIN (the entire or parts of) the SSL certificate of server to prevent man-in-the-middle attacks.
Even though there are various approaches to do this, when you searching for thisI only found examples for pinning the entire certificate. Such practice poses a problem: As soon as the certificate is updated, your application will not be able to connect anymore.
If you choose to pin the public key instead of the entire certificate you will find yourself (I believe) in an equally secure situation, while being more resilient to certificate updates in the server.
But how do you do this?
In case you are in need of knowing how to extract this information from the certificate in your iOS code, here you have one way to do it.
First of all add the security framework.
#import <Security/Security.h>
The add the openssl libraries. You can download them from https://github.com/st3fan/ios-openssl
#import <openssl/x509.h>
The NSURLConnectionDelegate Protocol allows you to decide whether the connection should be able to respond to a protection space. In a nutshell, this is when you can have a look at the certificate that is coming from the server, and decide to allow the connection to proceed or to cancel. What you want to do here is compare the certificates public key with the one you've pinned. Now the question is, how do you get such public key? Have a look at the following code:
First get the certificate in X509 format (you will need the ssl libraries for this)
const unsigned char *certificateDataBytes = (const unsigned char *)[serverCertificateData bytes];
X509 *certificateX509 = d2i_X509(NULL, &certificateDataBytes, [serverCertificateData length]);
Now we will prepare to read the public key data
ASN1_BIT_STRING *pubKey2 = X509_get0_pubkey_bitstr(certificateX509);
NSString *publicKeyString = [[NSString alloc] init];
At this point you can iterate through the pubKey2 string and extract the bytes in HEX format into a string with the following loop
for (int i = 0; i < pubKey2->length; i++)
{
NSString *aString = [NSString stringWithFormat:#"%02x", pubKey2->data[i]];
publicKeyString = [publicKeyString stringByAppendingString:aString];
}
Print the public key to see it
NSLog(#"%#", publicKeyString);
The complete code
- (BOOL)connection:(NSURLConnection *)connection canAuthenticateAgainstProtectionSpace:(NSURLProtectionSpace *)protectionSpace
{
const unsigned char *certificateDataBytes = (const unsigned char *)[serverCertificateData bytes];
X509 *certificateX509 = d2i_X509(NULL, &certificateDataBytes, [serverCertificateData length]);
ASN1_BIT_STRING *pubKey2 = X509_get0_pubkey_bitstr(certificateX509);
NSString *publicKeyString = [[NSString alloc] init];
for (int i = 0; i < pubKey2->length; i++)
{
NSString *aString = [NSString stringWithFormat:#"%02x", pubKey2->data[i]];
publicKeyString = [publicKeyString stringByAppendingString:aString];
}
if ([publicKeyString isEqual:myPinnedPublicKeyString]){
NSLog(#"YES THEY ARE EQUAL, PROCEED");
return YES;
}else{
NSLog(#"Security Breach");
[connection cancel];
return NO;
}
}
As far as I can tell you cannot easily create the expected public key directly in iOS, you need to do it via a certificate.
So the steps needed are similar to pinning the certificate, but additionally you need to extract the public key from the actual certificate, and from a reference certificate (the expected public key).
What you need to do is:
Use a NSURLConnectionDelegate to retrieve the data, and implement willSendRequestForAuthenticationChallenge.
Include a reference certificate in DER format. In the example I've used a simple resource file.
Extract the public key presented by the server
Extract the public key from your reference certificate
Compare the two
If they match, continue with the regular checks (hostname, certificate signing, etc)
If they don't match, fail.
Some example code:
(void)connection:(NSURLConnection *)connection willSendRequestForAuthenticationChallenge:(NSURLAuthenticationChallenge *)challenge {
// get the public key offered by the server
SecTrustRef serverTrust = challenge.protectionSpace.serverTrust;
SecKeyRef actualKey = SecTrustCopyPublicKey(serverTrust);
// load the reference certificate
NSString *certFile = [[NSBundle mainBundle] pathForResource:#"ref-cert" ofType:#"der"];
NSData* certData = [NSData dataWithContentsOfFile:certFile];
SecCertificateRef expectedCertificate = SecCertificateCreateWithData(NULL, (__bridge CFDataRef)certData);
// extract the expected public key
SecKeyRef expectedKey = NULL;
SecCertificateRef certRefs[1] = { expectedCertificate };
CFArrayRef certArray = CFArrayCreate(kCFAllocatorDefault, (void *) certRefs, 1, NULL);
SecPolicyRef policy = SecPolicyCreateBasicX509();
SecTrustRef expTrust = NULL;
OSStatus status = SecTrustCreateWithCertificates(certArray, policy, &expTrust);
if (status == errSecSuccess) {
expectedKey = SecTrustCopyPublicKey(expTrust);
}
CFRelease(expTrust);
CFRelease(policy);
CFRelease(certArray);
// check a match
if (actualKey != NULL && expectedKey != NULL && [(__bridge id) actualKey isEqual:(__bridge id)expectedKey]) {
// public keys match, continue with other checks
[challenge.sender performDefaultHandlingForAuthenticationChallenge:challenge];
} else {
// public keys do not match
[challenge.sender cancelAuthenticationChallenge:challenge];
}
if(actualKey) {
CFRelease(actualKey);
}
if(expectedKey) {
CFRelease(expectedKey);
}
}
Disclaimer: this is example code only, and not thoroughly tested.
For a full implementation start with the certificate pinning example by OWASP.
And remember that certificate pinning can always be avoided using SSL Kill Switch and similar tools.
You can do public key SSL pinning using the SecTrustCopyPublicKey function of the Security.framework. See an example at connection:willSendRequestForAuthenticationChallenge: of the AFNetworking project.
If you need openSSL for iOS, use https://gist.github.com/foozmeat/5154962 It's based on st3fan/ios-openssl, which currently doesn't work.
You could use the PhoneGap (Build) plugin mentioned here: http://www.x-services.nl/certificate-pinning-plugin-for-phonegap-to-prevent-man-in-the-middle-attacks/734
The plugin supports multiple certificates, so the server and client don't need to be updated at the same time. If your fingerprint changes every (say) 2 year, then implement a mechanism for forcing the clients to update (add a version to your app and create a 'minimalRequiredVersion' API method on the server. Tell the client to update if the app version is too low (f.i. when the new certificate is activate).
If you use AFNetworking (more specifically, AFSecurityPolicy), and you choose the mode AFSSLPinningModePublicKey, it doesn't matter if your certificates change or not, as long as the public keys stay the same. Yes, it is true that AFSecurityPolicy doesn't provide a method for you to directly set your public keys; you can only set your certificates by calling setPinnedCertificates. However, if you look at the implementation of setPinnedCertificates, you'll see that the framework is extracting the public keys from the certificates and then comparing the keys.
In short, pass in the certificates, and don't worry about them changing in the future. The framework only cares about the public keys in those certificates.
The following code works for me.
AFHTTPRequestOperationManager *manager = [AFHTTPRequestOperationManager manager];
manager.securityPolicy = [AFSecurityPolicy policyWithPinningMode:AFSSLPinningModePublicKey];
[manager.securityPolicy setPinnedCertificates:myCertificate];
...for pinning the entire certificate. Such practice poses a problem...
Also, Google changes the certificate monthly (or so) but retains or re-certifies the public. So certificate pinning will result in a lot of spurious warnings, while public key pinning will pass key continuity tests.
I believe Google does it to keep CRLs, OCSP and Revocation Lists manageable, and I expect others will do it also. For my sites, I usually re-certify the keys so folks to ensure key continuity.
But how do you do this?
Certificate and Public Key Pinning. The article discusses the practice and offers sample code for OpenSSL, Android, iOS, and .Net. There is at least one problem with iOS incumbent to the framework discussed at iOS: Provide Meaningful Error from NSUrlConnection didReceiveAuthenticationChallenge (Certificate Failure).
Also, Peter Gutmann has a great treatment of key continuity and pinning in his book Engineering Security.
If you use AFNetworking, use AFSecurityPolicy *policy = [AFSecurityPolicy policyWithPinningMode:AFSSLPinningModePublicKey];