Rijndael Encryption Keys - vb.net

I'm trying to understand why the code directly below does not require you to generate a IV key as well?? Code is from:
http://msdn.microsoft.com/en-us/library/sb7w85t6(v=vs.85).aspx
Dim key As RijndaelManaged = Nothing
Try
' Create a new Rijndael key.
key = New RijndaelManaged()
I see this sample code but requires you to generate both keys manaually?
Code is from:
http://msdn.microsoft.com/en-us/library/System.Security.Cryptography.RijndaelManaged(v=vs.110).aspx
Class RijndaelExample
Public Shared Sub Main()
Try
Dim original As String = "Here is some data to encrypt!"
' Create a new instance of the RijndaelManaged
' class. This generates a new key and initialization
' vector (IV).
Using myRijndael As New RijndaelManaged()
myRijndael.GenerateKey()
myRijndael.GenerateIV()
Also I plan to hardcode the key into the source(I know it's not the most secure)... how do I actually store these.. it looks like it will generate a new key everytime the application is open.

You're right, in that it will create a new key and IV every time you run. Instead, you should be creating a hash yourself (which is used to encrypt the data, and is derived from your password and a "salt" - see http://en.wikipedia.org/wiki/Salt_(cryptography))
For example,
SymmetricAlgorithm m_encryption;
RSACryptoServiceProvider m_rsa;
Rfc2898DeriveBytes m_hash;
string password = "Pa55w0rd";
string salt = "this is my salt. There are many like it, but this one is mine.";
public void SetupEncryption()
{
m_encryption = new RijndaelManaged();
m_hash = new Rfc2898DeriveBytes(password, Encoding.ASCII.GetBytes(salt));
m_encryption.Key = m_hash.GetBytes(m_encryption.KeySize / 8);
m_encryption.IV = m_hash.GetBytes(m_encryption.BlockSize / 8);
}
As you've noted though, storing your salt and your password are very bad form! This is just an example to show how to get started. Take a good look through wikipedia and other articles until you fully understand the principles!

Related

"ERROR unspecified algorithm" when signing a PDF with itextsharp 5.5.13.2 and SHA-256

Good morning, I am trying to sign a PDF document using ItextSharp 5.5.13.2 and SHA-256 for the signature process but at the moment of signing I get the error "Specified Algorithm is Invalid". This error does not happen when I use SHA-1 with .NetFramework 4.7.2 to sign the PDF, the next method is the one I use to sign the PDF.
public void SignPDF(string PathSourceDoc, string PathTargetDoc, X509Certificate2 certificate, string pathLogo)
{
using (PdfReader reader = new PdfReader(PathSourceDoc))
using (var writer = new FileStream(PathTargetDoc, FileMode.Create, FileAccess.Write))
using (var stamper = PdfStamper.CreateSignature(reader, writer, '\0', null, true))
{
var signature = stamper.SignatureAppearance;
signature.CertificationLevel = PdfSignatureAppearance.NOT_CERTIFIED;
signature.Reason = "My Reason";
signature.Location = "My Location";
signature.SignDate = DateTime.Now;
signature.Acro6Layers = true;
PdfSignature objSignature = new PdfSignature(PdfName.ADOBE_PPKMS, PdfName.ADBE_PKCS7_SHA1);
objSignature.Date = new PdfDate(signature.SignDate);
signature.CryptoDictionary = objSignature;
var bcCert = DotNetUtilities.FromX509Certificate(certificate);
string name = CertificateInfo.GetSubjectFields(bcCert).GetField("CN");
string industry = CertificateInfo.GetSubjectFields(bcCert).GetField("O");
string position = CertificateInfo.GetSubjectFields(bcCert).GetField("T");
DateTime date = DateTime.Now;
signature.Layer2Text = "Digital Signed by: " + name + "\n" +
"Reason: " + "My Reason" + "\n" +
"Date: " + date;
signature.Layer2Font = new Font(iTextSharp.text.Font.FontFamily.TIMES_ROMAN, 8);
Image img = Image.GetInstance(pathLogo);
signature.SignatureGraphic = img;
signature.SignatureRenderingMode = PdfSignatureAppearance.RenderingMode.GRAPHIC_AND_DESCRIPTION;
Rectangle rect = new Rectangle(50, 50, 300, 110);
signature.SetVisibleSignature(rect, 1, null);
var standard = CryptoStandard.CADES;
/*I tried this way but I get an error of type Internal.Cryptography.CryptoThrowHelper.WindowsCryptographicException: 'The requested operation is not supported.'*/
X509Certificate cert = certificate;
X509Certificate2 signatureCert = new X509Certificate2(cert);
var pk = Org.BouncyCastle.Security.DotNetUtilities.GetKeyPair(signatureCert.PrivateKey).Private;// the error is generated in this line (Internal.Cryptography.CryptoThrowHelper.WindowsCryptographicException: 'The requested operation is not supported.').
IExternalSignature es = new PrivateKeySignature(pk, "SHA-256");
/****************************************************************************************************************************************************************/
X509Certificate2Signature externalSignature = new X509Certificate2Signature(certificate, DigestAlgorithms.SHA1); /*throws an exception on this line of type "System.ArgumentException: 'Unknown encryption algorithm System.Security.Cryptography.RSACng'"
* when using .NET Core 3.1. this always happens, it doesn't matter if I use sha1 or use any other algorithm, it always generates error*/
MakeSignature.SignDetached(signature, externalSignature, new[] { bcCert }, null, null, null, 0, standard);
}
}
The method receives as input parameters the path of the PDF that I need to sign, the path of the pdf that will be created when signing, the certificate and the path of the logo for displaying the image in the signature. Actually I don't know what I'm doing wrong since I've been researching related questions and it should work with SHA-1 and SHA-256 and .NetFramework.
Then I migrated the project to .NetCore 3.1 in order to try to fix the problem but instead I got a new error (It is commented in the code). My goal is to use .NetCore and to allow me to sign a pdf using sha256. I have no problem modifying the SignPdf method in order to make the program work.
Any contribution or information link is appreciated. Thanks for your help.
Psdt: This is the stacktrace is as follows...
this is the stacktrace image of the error when the project was migrated to .Net Core 3.1
Apparently the Microsoft Crypto APIs used by X509Certificate2Signature do not support SHA-256.
You use a X509Certificate2Signature instance as IExternalSignature argument of MakeSignature.SignDetached.
If the PrivateKey of your X509Certificate2 is a RSACryptoServiceProvider (which appears to be the case for your certificate), X509Certificate2Signature.Sign calls
RSACryptoServiceProvider rsa = (RSACryptoServiceProvider)certificate.PrivateKey;
return rsa.SignData(message, hashAlgorithm);
RSACryptoServiceProvider.SignData at first apparently does support "SHA256" because before forwarding execution to SignHash it must have calculated the hash value to sign.
RSACryptoServiceProvider.SignHash, though, does not support SHA-256, according to the Microsoft docs on that method:
Remarks
This method creates a digital signature that is verified using the VerifyHash method.
The valid hash algorithms are SHA1 and MD5. The algorithm identifier can be derived from the hash name by using the MapNameToOID method.
Due to collision problems with SHA1 and MD5, Microsoft recommends a security model based on SHA256 or better.
(Viewed 2021-06-24, 11:07)
Thus, you get the "Specified Algorithm is Invalid" error.
Essentially, therefore, one should not base one's IExternalSignature implementation for RSA signing on RSACryptoServiceProvider anymore.
Maybe this is why X509Certificate2Signature was not ported to iText version 7...
An alternative approach might be to check whether the PrivateKey is a RSACng first and in that case use it as a RSACng. This Cryptography Next Generation (CNG) implementation of the RSA algorithm should support better hashing algorithms...

iText 7 PDF signing with GlobalSign DSS

I'm digitally signing a PDF using iText 7 in an asp.net app. I'm using vb but I could figure out a c# answer, too. We're using GlobalSign DSS in order to have the signature not come up as UNKNOWN (AATL).
I created a pfx file from our company SSL certificate and I am able to sign the PDF files using that file but I don't understand how to use the things I get from GlobalSign to accomplish the same thing. This service requires to send a hex encoded SHA256 digest and in return I receive a hex encoded signatureValue. Besides that I also receive a PEM encoded X509 signing certificate, intermediate certificate (PEM encoded X509 certificate that represents the issuer of the signing certificate), Base64 encoded DER representation of the OCSP response for signing_certificate, a Base64 encoded DER representation of timestamp token. It includes the TSA signing certificate in SignedData.CertificatesSet.
I created the code below as best as I could with limited examples from the internet for itext 7 and my even more limited knowledge of PDF signing and certificates in general. I know now that there are some things I make that I don't even use properly such as the tsaClient and the crlList. I didn't quite understand what those were until I had to switch to the DSS. I actually still don't know what the crlList would be although I think it has something to do with a chain, although I don't quite know what a chain is in this context.
Dim outputFileStream As New FileStream(Server.MapPath(strDest), IO.FileMode.Create, IO.FileAccess.ReadWrite)
Dim signer As New PdfSigner(New PdfReader(Server.MapPath(strTemp)), outputFileStream, True)
signer.SetCertificationLevel(PdfSigner.CERTIFIED_FORM_FILLING_AND_ANNOTATIONS)
Dim appearance As PdfSignatureAppearance = signer.GetSignatureAppearance
Dim rect As New iText.Kernel.Geom.Rectangle(50, 425, 500, 200)
appearance.SetContact("Contact Name - Phone")
appearance.SetSignatureCreator("Company - New Program")
appearance.SetReason(vbCrLf + "eDoc Consent Agreement: " + CType(Session("eDocConsentDateTime"), Date).ToString + vbCrLf _
+ "Terms and Conditions Agreement: " + objInstall.AgreementSigned.ToString + vbCrLf _
+ "Identifier: " + Session("Ident"))
appearance.SetLocation(vbCrLf + strInstallationAddress)
appearance.SetReuseAppearance(False)
appearance.SetPageRect(rect)
appearance.SetPageNumber(2) 'Signature will appear on Page 2
appearance.SetRenderingMode(PdfSignatureAppearance.RenderingMode.DESCRIPTION)
signer.SetFieldName(signer.GetNewSigFieldName())
Dim cert As New X509Certificate(Server.MapPath("CompSSL.pfx"), "password")
Dim tsaUrl As String = CertificateUtil.GetTSAURL(DotNetUtilities.FromX509Certificate(cert))
tsaClient = New TSAClientBouncyCastle(tsaUrl)
Dim crlList As IList(Of ICrlClient) = New List(Of ICrlClient)()
Dim fsCertFile As New FileStream(Server.MapPath("CompSSL.pfx"), FileMode.Open, FileAccess.Read)
Dim pk12 As New Pkcs12Store(fsCertFile, "password")
fsCertFile.Dispose()
'then Iterate throught certificate entries to find the private key entry
Dim [alias] As String = Nothing
For Each tAlias As String In pk12.Aliases
If pk12.IsKeyEntry(tAlias) Then
[alias] = tAlias
Exit For
End If
Next
Dim pk = pk12.GetKey([alias]).Key
Dim myExternalSignature As IExternalSignature = New PrivateKeySignature(pk, DigestAlgorithms.SHA1)
signer.SignDetached(myExternalSignature, New Org.BouncyCastle.X509.X509Certificate() {pk12.GetCertificate([alias]).Certificate}, Nothing, Nothing, Nothing, 0, PdfSigner.CryptoStandard.CMS)
So I'd like to know how I can use the GlobalSign pieces in order to sign the PDF. It almost seems like they are giving me everything I need to plug into the SignDetached method at the very end but I specifically don't know these things:
I believe that I'm supposed to do the hash to create the digest AFTER I've added the appearance stuff but I don't know what I would pass those bytes to something like Dim hash() As Byte = s.ComputeHash(fileBytes) at that point in my code (right after signer.SetFieldName(signer.GetNewSigFieldName()) I assume)
I don't know how or if I use the two certificates I get from the DSS. I even saw an example that suggests I may put them together to get something.
I don't know if the Signature Value I get is the equivalent of the IExternalSignature. If so, I don't know how to convert it to type "Org.BouncyCastle.Crypto.ICipherParameters" or even if I'm supposed to be trying to.
I plug the timestamp token string I get back from the DSS into the line tsaClient = New TSAClientBouncyCastle(tsaUrl) in the place of "tsaUrl" and there is no error but I don't know if that's right.
I don't know what to do with the OCSP response that I get from the DSS to put it into an IOcspClient object.
If I don't even try to put in the timestamp or the OCSP response in, as apparently I don't in the .pfx version of my code, what will that mean?
What are the data type conversions I'll have to do, if any, to make the DSS responses work?
I've tried to follow the iTextsharp examples, even this one (itextsharp signing pdf with signed hash) which is exactly what I'm trying to do but it doesn't seem to give me the info I need to finish it off. Thanks for your help.
EDIT:
Thanks for the help, dsandoval. I went ahead and hash the unchanged file and that's what I send to GlobalSign:
Dim s As New SHA256Managed
Dim fileBytes() As Byte = IO.File.ReadAllBytes(Server.MapPath(strSrc))
Dim hash() As Byte = s.ComputeHash(fileBytes)
Dim calculatedHash As String = ByteArrayToString(hash)
With this too:
Private Function ByteArrayToString(ByVal arrInput() As Byte) As String
Dim sb As New System.Text.StringBuilder(arrInput.Length * 2)
For i As Integer = 0 To arrInput.Length - 1
sb.Append(arrInput(i).ToString("X2"))
Next
Return sb.ToString().ToUpper
End Function
Then I wrote the two certificates I get from GS to files and then use BouncyCastle to read them into certificates and put them into an array (signing cert first). I pick up where I am writing the second cert file from their 'certificate_path' string here:
Using sw As New StreamWriter(File.Open(strFile2, FileMode.OpenOrCreate))
sw.WriteLine(strTempCert2)
End Using
Dim fileStream2 = System.IO.File.OpenText(strFile2)
Dim pemReader2 = New Org.BouncyCastle.OpenSsl.PemReader(fileStream2)
Dim myCertificateChain() As Org.BouncyCastle.X509.X509Certificate = New Org.BouncyCastle.X509.X509Certificate() {pemReader.ReadObject, pemReader2.ReadObject}
I did the same thing you did with IExternalSignature using this to convert the string from GS:
Private Function StringToByteArray(s As String) As Byte()
' remove any spaces from, e.g. "A0 20 34 34"
s = s.Replace(" "c, "")
' make sure we have an even number of digits
If (s.Length And 1) = 1 Then
Throw New FormatException("Odd string length when even string length is required.")
End If
' calculate the length of the byte array and dim an array to that
Dim nBytes = s.Length \ 2
Dim a(nBytes - 1) As Byte
' pick out every two bytes and convert them from hex representation
For i = 0 To nBytes - 1
a(i) = Convert.ToByte(s.Substring(i * 2, 2), 16)
Next
Return a
End Function
For now I'm just including the certificate chain and the signature and not the timestamp or the OCSP to see if I can just get it signed. With the certificate chain and the implementation of IExternalSignature, I'm able to get SignDetached to run:
signer.SignDetached(myExternalSignature, myCertificateChain, Nothing, Nothing, Nothing, 0, PdfSigner.CryptoStandard.CMS)
The PDF is signed but the signature panel says "Certification by is invalid", "Certified by %s". The details say "There are errors in the formatting or information contained in this signature". When clicking on "Certificate details", nothing happens. I found another person online with this error (Error signing pdf with PHP's openssl_pkcs7_sign) and it was due to the signature container being too big. The zero in my SignDetached parameters is supposed to be "estimate the size" so I changed it to 8192 which was a magic number of 8k I found in some other examples online. That didn't help. Any suggestions at this point?
I'm using c# for my implementation. I'm not too familiar with VB but hopefully this helps. Most of the examples I've seen are using Java and there were some differences in how they implement this, so I had to work around them. The only things I had to implement for this work was the IExternalSignature, IOcspClient, and ITsaClient.
The digest that is sent to GlobalSign are the contents of the document prior to applying to the signature, so the appearance can be left out if applied with signature. The document is not modified until you apply the signature using the PdfSigner.SignDetached, I believe. To compute the digest, you need to use the SHA256 algorithm to hash the message and hexencode it. This is the digest that will be sent to GS.
You need to put both the certificates from GlobalSign to create the certificate chain. First add the signing certificate then the certificate you can retrieve from their 'certificate_path' endpoint.
I'm not sure about the conversion to that type, but with the c# library, the Sign method of IExternalSignature returns a byte[]. With my own implementation of the interface, I simply converted the SignatureValue we received from GS to a byte[].
For the timestamp, we also implemented our own ITsaClient that calls GS for the timestamp. The digest has to be calculated in the GetTimeStampToken method and sent to GS. The response is a hexencoded string that we convert to a byte[].
For the OCSP, we also implemented our own IOcspClient. Since we get the ocsp_response when we fetch the identity, this client simply uses that, rather than calling GS again. I had issues enabling LTV when returning the response by only converting it from a Base64 string to a byte[]. BouncyCastle had trouble reading the response in this format. I had to convert it to the following BouncyCastle objects for this to work properly.
public byte[] GetEncoded( X509Certificate checkCert, X509Certificate issuerCert, string url )
{
var decoded = Base64.Decode(_ocspResponse); //_ocspResponse is same one that we received when fecthing the identity
var response = new OcspResp(decoded);
var basicResponse = (BasicOcspResp)response.GetResponseObject();
return basicResponse.GetEncoded();
}
If no timestamp is attached, the signature will not be timestamped. It will display the time as something along the lines of "the time is time on the signer's computer's system clock" when you open the document in Adobe. If no ocsp response is attatched, the person validating will not have a way to validate that the certificate has/hasn't been revoked at the time of the signature.
I believe the only conversions I had to make were the one mentioned above.
Let me know if you need any more code examples or any other questions.
EDIT
Here is the IExternalSignature implementation. The hash and encryption algorithm has to match what GS will use. They are using SHA256 and RSA.
public class ExternalSignature : IExternalSignature
{
private readonly SigningIdentity _identity;
private readonly GlobalSignClient _client;
public ExternalSignature( GlobalSignClient client, SigningIdentity identity )
{
_client = client;
_identity = identity;
}
public string GetEncryptionAlgorithm() => "RSA";
public string GetHashAlgorithm() => DigestAlgorithms.SHA256;
public byte[] Sign( byte[] message )
{
// Using the System.Security.Cryptography implementation of SHA256
using (var sha = SHA256.Create())
{
// Hash the message, containing the PDF
var bytes = sha.ComputeHash(message);
// HexEconde the hashed message to send to GlobalSign
var digest = Helpers.ByteArrayToString(bytes);
// Send the digest to GlobalSign
var signature = _client.GetSignatureAsync(_identity.Id, digest).Result;
// Return the returned signature as a byte[]
return Helpers.StringToByteArray(signature);
}
}
}
To add the signature, just create an instance and pass it to SignDetached method.
var signature = new ExternalSignature(_client, signingIdentity);
...
...
//After creating the PDF signer, adding appearance, creating the OCSP and TSA clients.
signer.SignDetached(signature, certChain, null, ocsp, tsa, 0, PdfSigner.CryptoStandard.CMS);
I did the same with the OCSP and TSA clients.

generate password for auth-plug for mosquitto in c#

I have spent all day trying to make a usable pbkdf2 password for the mosquitto-auth-plug. This program sets it up exactly the way it should be stored in the mysql database. I have a password hash generated by the program that comes with auth-plug and mosquitto loves it. I just can't replicate it in c#, if anyone can help please let me know.
public string CreatePasswordHash(string password)
{
var salt = GenerateRandomSalt();
var iterationCount = GetIterationCount();
var hashValue = GenerateHashValue(password, salt, iterationCount);
string result = "PBKDF2$sha256$" + iterationCount + "$" + Convert.ToBase64String(salt) + "$" + Convert.ToBase64String(hashValue);
return result;
}
private int GetIterationCount()
{
return 901;
}
private static byte[] GenerateRandomSalt()
{
var csprng = new RNGCryptoServiceProvider();
var salt = new byte[SaltByteLength];
csprng.GetBytes(salt);
return salt;
//return GetLetter();
}
private static byte[] GenerateHashValue(string password, byte[] salt, int iterationCount)
{
byte[] hashValue;
var valueToHash = string.IsNullOrEmpty(password) ? string.Empty : password;
using (var pbkdf2 = new Rfc2898DeriveBytes(valueToHash, salt, iterationCount))
{
hashValue = pbkdf2.GetBytes(DerivedKeyLength);
}
return hashValue;
}
---EDIT-----
Rfc2898DeriveBytes states --
Implements password-based key derivation functionality, PBKDF2, by using psuedo-random number generator based on HMACSHA1.
The program/auth-plug seems to be using sha256 is there a c# PBKDF2 that uses this.
As you have already stated in your edit, the problem appears to be the difference in hash functions used between the mosquitto plugin (which only supports SHA-256, according to the source code) and the .NET implementation (which can only do SHA-1).
A more flexible implementation of PBKDF2 is available in BouncyCastle, a more lightweight implementation can be found here. If you are not satisfied with those two, you could chose to implemnt PBKDF2 yourself, which is not really hard.
Well it appears there really wasn't an answer and there weren't many who had tried. I figured out the problem and after contacting the mosquitto-auth-plug author he felt it would be good for us to add my solution to his contrib folder on the plugins github repo.
So now if you need a c# hashing algorithm for mosquitto-auth-plug just go to the repo in git here
https://github.com/jpmens/mosquitto-auth-plug/tree/master/contrib/C%23
and follow my instructions --- Let me know if you have any problems

Basic Sample (Java preferred) for Desire2Learn API

I have visited and read all the Valence, and specifically the REST API, pages. I have one approved key already and a second key that has not yet been approved by D2L, and it's not clear how I request that approval.
The documentation contains a lot of information, but it is difficult to put all the pieces together. For example, in order to make any REST API call, I have to add several parameters to the end of the call. The parameters are documented in one place, but it isn't clear in some cases how to construct them (for example, one of the keys is to contain the url, timestamp, and the type of call being made, but how are they to be concatenated?). Then they have to be signed, and the documentation that tells how to sign the keys is in a completely different page that is not even referenced from the page that tells you that you have to sign the parameters. On top of that, the documentation is not extremely clear about how to do the signing, and offers no further explanation or examples. So to get anywhere, we have to jump around a lot through the documentation, and go through a whole lot of trial and error. It appears that the documentation assumes that the reader has expertise in several areas, which may or may not be true.
Code examples would make a huge difference.
There aren’t a lot of samples yet; we are working to add more, and to make the ones that are present more obvious. As one example, there is a Java Android app that has all the authentication stuff and some basic calls (including the call “whoami” which is a great test call).
The specific auth related files are available as well. From the D2LSigner class, you can see the signing algorithm we use:
Mac hmacSha256 = Mac.getInstance("hmacSHA256");
byte[] keyBytes = key.getBytes("UTF-8");
Key k = new SecretKeySpec(keyBytes, "hmacSHA256");
hmacSha256.init(k);
byte[] dataBytes = data.getBytes("UTF-8");
byte[] sig = hmacSha256.doFinal(dataBytes)
String sigString = base64Url( sig );
From D2LOperationSecurityImpl, you can see how the query string fits together:
//uppercase METHOD, lowercase PATH, timestamp as string
private static /*final*/ String BASE_STRING_TEMPLATE = "{0}&{1}&{2}";
private static /*final*/ String APP_ID_QUERY_NAME = "x_a";
private static /*final*/ String APP_SIG_QUERY_NAME = "x_c";
private static /*final*/ String USER_ID_QUERY_NAME = "x_b";
private static /*final*/ String USER_SIG_QUERY_NAME = "x_d";
private static /*final*/ String TIMESTAMP_QUERY_NAME = "x_t";
...
#Override
public Uri createAuthenticatedUri(String path, String httpMethod) {
long timestamp = System.currentTimeMillis() +
mServerSkewCorrectionMillis.longValue();
Long timestampObjectSeconds = new Long(timestamp/1000);
Object[]formatParms = {httpMethod.toUpperCase(),
path.toLowerCase(),
timestampObjectSeconds.toString()};
String signatureBaseString = MessageFormat.format(BASE_STRING_TEMPLATE,
formatParms);
String appSig = D2LSigner.base64URLSig(mAppKey, signatureBaseString);
String userSig = D2LSigner.base64URLSig(mUserKey, signatureBaseString);
if ((appSig == null) || (userSig == null)) {
return null;
}
String scheme = mEncryptOperations?ENCRYPED_SCHEME:PLAIN_SCHEME;
Uri.Builder b = new Uri.Builder();
b.scheme(scheme);
b.authority(mHostName);
b.path(path);
b.appendQueryParameter(APP_ID_QUERY_NAME, mAppID);
b.appendQueryParameter(APP_SIG_QUERY_NAME, appSig);
b.appendQueryParameter(USER_ID_QUERY_NAME, mUserID);
b.appendQueryParameter(USER_SIG_QUERY_NAME, userSig);
b.appendQueryParameter(TIMESTAMP_QUERY_NAME, timestampObjectSeconds.toString());
Uri securedURI = b.build();
return securedURI;
}
Also, you need to sign the first URL you use for logging in, but only with the application key (because you haven't yet established a user context). It uses a different base string (to protect the URL that is used during auth):
String signature = D2LSigner.base64URLSig(mAppKey, resultURLString);
BasicNameValuePair appID = new BasicNameValuePair(APP_ID_NAME, mAppID);
BasicNameValuePair appSig = new BasicNameValuePair(APP_SIG_NAME, signature);
BasicNameValuePair callbackURL = new BasicNameValuePair(CALLBACK_NAME, resultURLString);

How can I do a search with Google Custom Search API for .NET?

I just discovered the Google APIs Client Library for .NET, but because of lack of documentation I have a hard time to figure it out.
I am trying to do a simple test, by doing a custom search, and I have looked among other, at the following namespace:
Google.Apis.Customsearch.v1.Data.Query
I have tried to create a query object and fill out SearchTerms, but how can I fetch results from that query?
My bad, my first answer was not using the Google APIs.
As a pre-requisite, you need to get the Google API client library
(In particular, you will need to reference Google.Apis.dll in your project). Now, assuming you've got your API key and the CX, here is the same code that gets the results, but now using the actual APIs:
string apiKey = "YOUR KEY HERE";
string cx = "YOUR CX HERE";
string query = "YOUR SEARCH HERE";
Google.Apis.Customsearch.v1.CustomsearchService svc = new Google.Apis.Customsearch.v1.CustomsearchService();
svc.Key = apiKey;
Google.Apis.Customsearch.v1.CseResource.ListRequest listRequest = svc.Cse.List(query);
listRequest.Cx = cx;
Google.Apis.Customsearch.v1.Data.Search search = listRequest.Fetch();
foreach (Google.Apis.Customsearch.v1.Data.Result result in search.Items)
{
Console.WriteLine("Title: {0}", result.Title);
Console.WriteLine("Link: {0}", result.Link);
}
First of all, you need to make sure you've generated your API Key and the CX. I am assuming you've done that already, otherwise you can do it at those locations:
API Key (you need to create a new browser key)
CX (you need to create a custom search engine)
Once you have those, here is a simple console app that performs the search and dumps all the titles/links:
static void Main(string[] args)
{
WebClient webClient = new WebClient();
string apiKey = "YOUR KEY HERE";
string cx = "YOUR CX HERE";
string query = "YOUR SEARCH HERE";
string result = webClient.DownloadString(String.Format("https://www.googleapis.com/customsearch/v1?key={0}&cx={1}&q={2}&alt=json", apiKey, cx, query));
JavaScriptSerializer serializer = new JavaScriptSerializer();
Dictionary<string, object> collection = serializer.Deserialize<Dictionary<string, object>>(result);
foreach (Dictionary<string, object> item in (IEnumerable)collection["items"])
{
Console.WriteLine("Title: {0}", item["title"]);
Console.WriteLine("Link: {0}", item["link"]);
Console.WriteLine();
}
}
As you can see, I'm using a generic JSON deserialization into a dictionary instead of being strongly-typed. This is for convenience purposes, since I don't want to create a class that implements the search results schema. With this approach, the payload is the nested set of key-value pairs. What interests you most is the items collection, which is the search result (first page, I presume). I am only accessing the "title" and "link" properties, but there are many more than you can either see from the documentation or inspect in the debugger.
look at API Reference
using code from google-api-dotnet-client
CustomsearchService svc = new CustomsearchService();
string json = File.ReadAllText("jsonfile",Encoding.UTF8);
Search googleRes = null;
ISerializer des = new NewtonsoftJsonSerializer();
googleRes = des.Deserialize<Search>(json);
or
CustomsearchService svc = new CustomsearchService();
Search googleRes = null;
ISerializer des = new NewtonsoftJsonSerializer();
using (var fileStream = new FileStream(filename, FileMode.Open, FileAccess.Read, FileShare.ReadWrite))
{
googleRes = des.Deserialize<Search>(fileStream);
}
with the stream you can also read off of webClient or HttpRequest, as you wish
Google.Apis.Customsearch.v1 Client Library
http://www.nuget.org/packages/Google.Apis.Customsearch.v1/
you may start from Getting Started with the API.