SharpSNMP: Using SNMP v3 with AES Privacy - vb.net

I have configured 2 users on a SNMP v3 server (a Cisco router):
A user that uses DES as the privacy method (desuser)
A user that uses AES 128 as the privacy method (aesuser)
The privacy password and the authentication password for both the users were set to the same: 12345678 for testing purposes.
Using the code in the link below (at end of question), I was able to perform SNMP v3 queries using DES as the privacy method. For this I used the following command line args:
-v=3 -l=authPriv -a=MD5 -A=12345678 -x=DES -X=12345678 -u=desuser 10.10.10.1 1.3.6.1.2.1.2.2.1.7.1
The above worked without any issue.
I then tried to use AES 128 as the privacy method by changing the privacy method and the user on the command line args as below:
-v=3 -l=authPriv -a=MD5 -A=12345678 -x=AES -X=12345678 -u=aesuser 10.10.10.1 1.3.6.1.2.1.2.2.1.7.1
This resulted in a TimeoutException:
I am able to use both these users (aesuser and desuser) on other SNMP agents without any issue.
Please let me know:
What needs to be specified in the command line arg -x when using AES 128? Should it be just AES or AES128?
When I reviewed the code for snmpget (in the link at the end), I noticed that the value assigned to the command line arg -x is assigned to a variable called privacy. However, this variable is never used later in the code when setting the IPrivacyProvider object. The only two code paths available when setting the this object is DESPrivacyProvider and DefaultPrivacyProvider. (see code extract below) Shouldn't these be something like AESPrivacyProvider that would enable the AES privacy method on the code?
Code extract from the snmpget project's Program.vb:
Dim priv As IPrivacyProvider
If ((level And Levels.Privacy) = Levels.Privacy) Then
priv = New AESPrivacyProvider(New OctetString(privPhrase), auth)
Else
priv = New DefaultPrivacyProvider(auth)
End If
https://github.com/lextm/sharpsnmplib/blob/master/Samples/VB.NET/snmpget/

http://help.sharpsnmp.com/html/T_Lextm_SharpSnmpLib_Security_AESPrivacyProvider.htm
As the documentation states, AES support is experimental.
You can write your own privacy provider to handle such algorithms, and it is purely a cryptography challenge and does not fall in #SNMP's scope (which only covers core SNMP features).

Related

How to use a private key that is stored on an HSM that is secured by a user password via Pkcs11Interop OR CNG?

Summary
Use CNG or Pkcs11Interop or any other alternatives to login to an HSM, search for a privatekey then pass it on to a 3rd party application for use.
The key cannot be extracted from the HSM or stored in memory.
a 3rd Party application needs to make use of a private key that is stored on a Hardware Security Module (HSM).
I have looked into two methods CNG and Pkcs11Interop.
The code needs to accomplish the following:
1-Authenticate and establish a session with the HSM
2-Search for the key
3-Pass the private key to the 3rd party using RSACryptoServiceProvider or other methods.
Important: The key cannot be accessed extracted from the HSM or access directly (by design for security purposes).
Below are the two samples I've put together for both CNG and PKCS11Interop
The Problem:
1-CNG I am struggling to authenticate (if that's possible)
2-PKCS11Interop I've been able to login, search for the key but struggling to make use of the key.
Happy to use either of the methods, and I welcome any assistance, alternative solutions or advice.
CNG Code:
This code works when authentication is disabled on HSM
Q. Is there a way to authenticate using a password , open a session prior to using the key?
CngProvider provider = new CngProvider("CNGProvider");
const string KeyName = "somekey";
key = CngKey.Open(KeyName, provider);
Console.WriteLine("found the key!");
var cngRsa = new RSACng(key);
var privateSshKey = new SshPrivateKey(cngRsa);
PKCS11Interop, I managed to authenticate, search for the key and assign it to a handle..
Q. How do i go about passing the private key onto a standard .Net Framework type AsymmetricAlgorithm? while keeping in mind it not exportable?
can it be passed to RSACryptoServiceProvider? and then onto AsymmetricAlgorithm?
using (IPkcs11Library pkcs11Library = Settings.Factories.Pkcs11LibraryFactory.LoadPkcs11Library(Settings.Factories, Settings.Pkcs11LibraryPath, Settings.AppType))
{
ISlot slot = Helpers.GetUsableSlot(pkcs11Library);
using (ISession session = slot.OpenSession(SessionType.ReadWrite))
{
//search for key
try
{
const string keyname = "somekey";
// Login as normal user
session.Login(CKU.CKU_USER, Settings.NormalUserPin);
IObjectHandle publicKeyHandle = Helpers.CreateDataObject(session);
IObjectHandle privateKeyHandle = Helpers.CreateDataObject(session);
// Prepare attribute template that defines search criteria
List<IObjectAttribute> privateKeyAttributes = new List<IObjectAttribute>();
privateKeyAttributes.Add(session.Factories.ObjectAttributeFactory.Create(CKA.CKA_CLASS, CKO.CKO_PRIVATE_KEY));
privateKeyAttributes.Add(session.Factories.ObjectAttributeFactory.Create(CKA.CKA_KEY_TYPE, CKK.CKK_RSA));
privateKeyAttributes.Add(session.Factories.ObjectAttributeFactory.Create(CKA.CKA_LABEL, keyname));
List<IObjectHandle> foundPrivateKeys = session.FindAllObjects(privateKeyAttributes);
if (foundPrivateKeys == null || foundPrivateKeys.Count != 1)
throw new Exception("Unable to find private key");
// Use found object handles
privateKeyHandle = foundPrivateKeys[0];
session.FindObjectsFinal();
// How do i go about using the privatekey handle here?
session.DestroyObject(privateKeyHandle);
session.Logout();
}
catch (Exception ex)
{
Console.WriteLine("Crypto error: " + ex.Message);
}
Console.WriteLine("done!");
System.Console.Write("[Hit Enter to Continue]");
System.Console.ReadLine();
}
}
With an HSM, by design, you cannot "Pass the private key to a 3rd party app".
You also cannot pass the key handle between processes (although this might work in some implementations - a key handle should be PKCS11 session specific).
Your 3rd party app needs to offload cryptographic operations to the HSM by using a configurable cryptography library like OpenSSL (or similar) or if it is using CNG it should allow you to configure the provider.
Q. Is there a way to authenticate using a password , open a session prior to using the key?
A.: For an app that uses CNG, you should use the CNG Key Storage Provider (KSP) from the HSM Vendor after you have configured it.
The HSM Vendor KSP will then prompt for the password or, if you configured the provider (using a utility or configuration file from the HSM vendor) to store the password/pin, it will just work.
eHSM sample code using NCryptNative:
SafeNCryptProviderHandle handle;
NCryptOpenStorageProvider(handle, "eHSM Key Storage Provider",0);
...
Q. How do i go about passing the private key onto a standard .Net Framework type AsymmetricAlgorithm? while keeping in mind it not exportable? can it be passed to RSACryptoServiceProvider? and then onto AsymmetricAlgorithm?
A.: No, you cannot pass key material and you cannot pass the raw PKCS11 handle to the CNG Framework. You either have to use the PKCS11Interop functions to perform all cryptographic operations OR you have to do everything in CNG (correctly configured as above).
To directly use the PKCS11 interface you continue calling PKCS11 functions with the key handle, ie.
// How do i go about using the privatekey handle here?
// something like this
session.SignInit(mechanism, privateKeyHandle);
session.Sign(data, signature));

XMPP SASL SCRAM-SHA1 Authentication

Recently, I was able to get MD5 authentication working for XMPP streams in Swift IOS following the instructions on the following two websites (I used the CC-MD5 function of Apple's CommonCrypto C library for the actual hashing):
http://wiki.xmpp.org/web/SASLandDIGEST-MD5
http://www.deusty.com/2007/09/example-please.html
I'm searching for a similar explanation for how to get other hashed SASL authentication schemes working, especially SCRAM-SHA1. I have found the official RFC5802 document but I'm having a lot of trouble understanding it (it is not specific to XMPP either). I would appreciate a simpler explanation or some simple readable code (C, PHP, C++, Javascript, Java) specific to XMPP authentication that doesn't use libraries for anything other than the actual hashing.
I'm interested in understanding the process and am not looking to use the ios XMPP-Framework. Any help would be appreciated.
SCRAM-SHA-1
The basic overview of how this mechanism works is:
The client sends the username it wants to authenticate as.
The server sends back the salt for that user and the number of iterations (either by generating them or looking them up in its database for the given username).
The client hashes the password with the given salt for the given number of iterations.
The client sends the result back.
The server does a variation of the hashing and sends it result back to the client, so the client can also verify that the server had the password/a hash of the password.
The cryptographic algorithms you'll need are SHA-1, HMAC with SHA-1 and PBKDF2 with SHA-1. You should look up how to use them in your language/framework, as I don't recommend implementing them from scratch.
In detail
First normalize the password (using SASLprep), this will be normalizedPassword. This is to ensure the UTF8 encoding can't contain variations of the same password.
Pick a random string (for example 32 hex encoded bytes). This will be clientNonce.
The initialMessage is "n=" .. username .. ",r=" .. clientNonce (I'm using .. for string concatenation).
The client prepends the GS2 header ("n,,") to the initialMessage and base64-encodes the result. It sends this as its first message:
<auth xmlns="urn:ietf:params:xml:ns:xmpp-sasl" mechanism="SCRAM-SHA-1">
biwsbj1yb21lbyxyPTZkNDQyYjVkOWU1MWE3NDBmMzY5ZTNkY2VjZjMxNzhl
</auth>
The server responds with a challenge. The data of the challenge is base64 encoded:
<challenge xmlns="urn:ietf:params:xml:ns:xmpp-sasl">
cj02ZDQ0MmI1ZDllNTFhNzQwZjM2OWUzZGNlY2YzMTc4ZWMxMmIzOTg1YmJkNGE4ZTZmODE0YjQyMmFiNzY2NTczLHM9UVNYQ1IrUTZzZWs4YmY5MixpPTQwOTY=
</challenge>
The client base64 decodes it:
r=6d442b5d9e51a740f369e3dcecf3178ec12b3985bbd4a8e6f814b422ab766573,s=QSXCR+Q6sek8bf92,i=4096
The client parses this:
r= This is the serverNonce. The client MUST ensure that it starts with the clientNonce it sent in its initial message.
s= This is the salt, base64 encoded (yes, this is base64-encoded twice!)
i= This is the number of iterations, i.
The client computes:
clientFinalMessageBare = "c=biws,r=" .. serverNonce
saltedPassword = PBKDF2-SHA-1(normalizedPassword, salt, i)
clientKey = HMAC-SHA-1(saltedPassword, "Client Key")
storedKey = SHA-1(clientKey)
authMessage = initialMessage .. "," .. serverFirstMessage .. "," .. clientFinalMessageBare
clientSignature = HMAC-SHA-1(storedKey, authMessage)
clientProof = clientKey XOR clientSignature
serverKey = HMAC-SHA-1(saltedPassword, "Server Key")
serverSignature = HMAC-SHA-1(serverKey, authMessage)
clientFinalMessage = clientFinalMessageBare .. ",p=" .. base64(clientProof)
The client base64 encodes the clientFinalMessage and sends it as a response:
<response xmlns="urn:ietf:params:xml:ns:xmpp-sasl">
Yz1iaXdzLHI9NmQ0NDJiNWQ5ZTUxYTc0MGYzNjllM2RjZWNmMzE3OGVjMTJiMzk4NWJiZDRhOGU2ZjgxNGI0MjJhYjc2NjU3MyxwPXlxbTcyWWxmc2hFTmpQUjFYeGFucG5IUVA4bz0=
</response>
If everything went well, you'll get a <success> response from the server:
<success xmlns='urn:ietf:params:xml:ns:xmpp-sasl'>
dj1wTk5ERlZFUXh1WHhDb1NFaVc4R0VaKzFSU289
</success>
Base64 decoded this contains:
v=pNNDFVEQxuXxCoSEiW8GEZ+1RSo=
The client MUST make sure the value of v is the base64 encoding of the serverSignature.
Extras
This is the basic version of the algorithm. You can extend it to do:
Channel binding. This mixes in some information from the TLS connection to the procedure to prevent MitM attacks.
Hashed storage. If the server always sends the same salt and i values, then the client can store only saltedPassword instead of the user's password. This is more secure (as the client doesn't need to store the password, just a hard to reverse salted hash) and faster, as the client doesn't need to do all the key stretching every time.
The server can also use hashed storage: the server can store only salt, i, storedKey and serverKey. More info on that here.
Possibly, also adding SCRAM-SHA-256 (though server support seems non-existent).
Pitfalls
Some common pitfalls:
Don't assume anything about the length of the nonces or salt (though if you generate them, make sure they are long enough and cryptographically random).
The salt is base64 encoded and can contain any data (embedded NULs).
Not using SASLprep may work fine for people using ASCII passwords, but it may completely break logging in for people using other scripts.
The initialMessage part of the authMessage does not include the GS2 header (in most situations, this is "n,,").
Test vectors
If you want to test your implementation, here are all the intermediate results for the example from the RFC:
Username: user
Password: pencil
Client generates the random nonce fyko+d2lbbFgONRv9qkxdawL
Initial message: n,,n=user,r=fyko+d2lbbFgONRv9qkxdawL
Server generates the random nonce 3rfcNHYJY1ZVvWVs7j
Server replies: r=fyko+d2lbbFgONRv9qkxdawL3rfcNHYJY1ZVvWVs7j,s=QSXCR+Q6sek8bf92,i=4096
The salt (hex): 4125c247e43ab1e93c6dff76
Client final message bare: c=biws,r=fyko+d2lbbFgONRv9qkxdawL3rfcNHYJY1ZVvWVs7j
Salted password (hex): 1d96ee3a529b5a5f9e47c01f229a2cb8a6e15f7d
Client key (hex): e234c47bf6c36696dd6d852b99aaa2ba26555728
Stored key (hex): e9d94660c39d65c38fbad91c358f14da0eef2bd6
Auth message: n=user,r=fyko+d2lbbFgONRv9qkxdawL,r=fyko+d2lbbFgONRv9qkxdawL3rfcNHYJY1ZVvWVs7j,s=QSXCR+Q6sek8bf92,i=4096,c=biws,r=fyko+d2lbbFgONRv9qkxdawL3rfcNHYJY1ZVvWVs7j
Client signature (hex): 5d7138c486b0bfabdf49e3e2da8bd6e5c79db613
Client proof (hex): bf45fcbf7073d93d022466c94321745fe1c8e13b
Server key (hex): 0fe09258b3ac852ba502cc62ba903eaacdbf7d31
Server signature (hex): ae617da6a57c4bbb2e0286568dae1d251905b0a4
Client final message: c=biws,r=fyko+d2lbbFgONRv9qkxdawL3rfcNHYJY1ZVvWVs7j,p=v0X8v3Bz2T0CJGbJQyF0X+HI4Ts=
Server final message: v=rmF9pqV8S7suAoZWja4dJRkFsKQ=
Server's server signature (hex): ae617da6a57c4bbb2e0286568dae1d251905b0a4

Getting error in extended operation for change password - [LDAP: error code 2 - unsupported extended operation]; remaining name ''

I want to reset password of any user in Sun one LDAP( or for that matter any other LDAP ) using extended operation. For the same, I have done following:
I have written two classes as follows:
PasswordExtendedRequest which implements ExtendedRequest AND
PasswordExtendedResponse which implements ExtendedResponse
I am using OID "1.3.6.1.4.1.4203.1.11.1" inside PasswordExtendedRequest
Following is code for extended operation
ExtendedRequest er = new PasswordExtendedRequest(<userName>,<password>);
ExtendedResponse extRes = (ExtendedResponse)ctx.extendedOperation(er);
But I am getting following error after execution and getResponseControls() is also returning NULL.
javax.naming.CommunicationException: [LDAP: error code 2 - unsupported extended operation]; remaining name ''
From the error it looks like that LDAP I am using, is not supporting this extended operation. What should I do with LDAP to support this reset password extended operation?
Let me know I am doing anything wrong or missing anything.
It appears that the Sun one LDAP server implementation you are using does not support the "1.3.6.1.4.1.4203.1.11.1" extension. To implement this extension would require the LDAP server administrator to implement it. (if the Sun One LDAP server CAN even support it)
Extensions are extensions beyond LDAP and may or may not be available on any given LDAP server.
You should be able to identify the support for the extension by querying the rootDSE and checking if the OID is present within the supportedExtension attribute.
-jim

What subject to use for SetClientCertificate?

I'm trying to send a request with:
ActiveXObject("WinHttp.WinHttpRequest.5.1")
however this requires a client certificate to do so (which we have been provided).
Having tested in PHP cURL I can do so with:
curl_setopt($SOAP, CURLOPT_SSLCERT,$filepathtocertificate);
Which works fine. However I must use IIS running asp(javascript) and point to the certificate store of the machine the script is running on with:
SetClientCertificate("LOCAL_MACHINE\\Personal\\Certificate subject");
for our actual deployment. The MS documentation (http://msdn.microsoft.com/en-us/library/windows/desktop/aa384055(v=vs.85).aspx) suggests that the path above has to state the 'subject' of the certificate, however the certificate seems to have several subjects and no combination of several or all of them seems to yeild any results and I am stuck with the following error before the request is even sent:
WinHttp.WinHttpRequest error '80072f0c'
A certificate is required to complete client authentication
Looking in the certificate store and using other scripts in the same folder show they are definitely there but have subjects like:
C=US, O=Organisation NAme, OU="Another Organisation Name, Inc.", CN=Organisation Name Root
Or similar.
Any advice on what parameters SetClientCertificate needs to be given to select and send certificates in the certificate store would be much appreciated.
I had a lot of trouble with this same issue - using winhttp 5.1 from a scripting language to set a client certificate before a send.
I had used mmc with the certificates snap-in to import the certificate in CURRENT_USER \ Personal - but the Winhttp SetClientCertificate didn't seem to be doing anything, nor was I able to pick up any error code or message so it was a case of repeated trial and error - the SetClientCertificate string should be something like "Location\store\subject" eg "CURRENT_USER\Personal\My Certificate" (or \ \ if your language requires \ to be escaped) -the final part being 'subject' which is not as clear as it should be. Under MMC the subject is broken into many elements.
I eventually got it working by dropping the location and store - they were the defaults so I may have been fortunate - and providing just the subject field - the value I used for the subject field was the value in the line "CN = " under subject (when the cert is opened under mmc) - but this (perhaps coincidentally) was also the value in the 'Issued To' column on the main mmc certificate list. In my case it worked - clearly if there is a cert with these two values different then you'd need to try each.
Hope this helps if somebody is similarly stuck.
This is a very old question yet I had to find an answer today. The answer provided above by #JSL helped me. If you only provide the certificate subject name then it works! So it is clear that there is a mistake in the way full path is specified.
I got the right info for Windows 7 from this link https://msdn.microsoft.com/en-us/library/windows/desktop/aa384076(v=vs.85).aspx
here is VBA script that works.
Dim objHttp As New WinHttp.WinHttpRequest
objHttp.Open "GET", url, False
objHttp.SetClientCertificate "CURRENT_USER\My\TestCert"
objHttp.send
Valid locations are LOCAL_MACHINE and CURRENT_USER and
Valid store names are "MY", "Root", and "TrustedPeople".
Remember to escape the backslashes in C++, C# etc.

How should an application authenticate with a datastore?

I'm writing an iPad game that sends hi-score type data (ie data beyond what Game Center supports) to a Google appengine datastore. It sends these updates via http GET or POST requests, such as http://myapp.appspot.com/game/hiscore/925818
Here is how I thought to ensure the appengine datastore isn't spammed with false data.
zip/encrypt the payload data using hardcoded p#ssw0rd saved in the iOS binary. Encode that binary data as base64. Pass base64 payload in the url query string or in the POST data. At handler, unbase64, then unzip data with p#ssw0rd. Follow instructions in payload to update highscore-type data.
CON: If p#ssw0rd is somehow derived from the iOS binary, this scheme can be defeated.
Is this adequate/sufficient? Is there another way to do this?
There is absolutely no way to make sure it's your client that sends the data. All you can try is to obfuscate some thing to make it harder for spammers to submit data.
However I think there are two thing you can do:
Have some kind of secrect key saved in the binary
Have a custom algorithm calculating some checksum
Maybe you can go with a combination of both. Let me give you an example:
Create some custom (complex!) alorithm like (simplyfied):
var result = ((score XOR score / 5) XOR score * 8) BITSHIFT_BY 3
Then use your static stored key with that result and a well known hash function like:
var hash = SHA256(StaticKey + result)
Then send that hash with the score to the server. The server has to "validate" the hash by performing the exact same steps (evaluate algorithm + do the SHA256 stuff) and compare the hashes. If they match the score hopefully comes from your app otherwise throw it away, it comes from a spammer.
However this is only one thing you can do. Have a look at the link from mfanto, there are many other ideas that you can look at.
Be sure to not tell anybody about how you're doing it since this is security through obscurity.
Ok me, there are 2 methods to do this.
1) Purchase an SSL certificate for $FREE.99 and open HTTPS connections only to your server to submit hiscore type data. Connection speed should be around 500 ms due to handshake roundtrip time.
2) Embed an RSA public key certificate in your iOS app, and have the RSA private key on your server.
You can then do 1 of 2 things with this second scheme:
IF your data messages are really small (≤256 B) you can just encrypt and send 256B packages (RSA payload is limited by the number of bits in the key)
ELSE IF the data is too large (>256B), generate a random symmetric key (AES), and pack:
SYMMETRIC AES KEY ENCRYPTED WITH RSA PUBLIC KEY
BINARY DATA ENCODED WITH SYMMETRIC AES KEY
The server then takes the first 256 bytes and decodes it, then the server uses that AES key to decrypt the rest of the message.
The above 2 only prevent eavesdropping, but it means the data format of your messages is hidden. At some level, it is still a type of security by obscurity, since if the hacker has your public key AND your message format, they can manufacture messages.