NetSuite RestLet SHA 256 Authentication - vb.net

I have an old running application. This application connect to Oracle NetSuite and send JSON data. It is written in VB.net and works fine. This application uses SHA1 to make authentication headers. I need to alter application to use SHA256 instead of SHA1. I tried Google and found few articles in python and C# but unfortunately there conversion in VB.net did not work here. Can someone kindly help to make this heading making process with SHA256 encryption. The current code is as below;
ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12 Or SecurityProtocolType.Tls11 Or SecurityProtocolType.Tls
Dim url As New Uri("https://xxxxxx.restlets.api.netsuite.com/app/site/hosting/restlet.nl?script=999&deploy=1")
Dim timestamp = OAuthBase.GenerateTimeStamp()
Dim nonce = OAuthBase.GenerateNonce()
Dim ckey = "01234" '//Consumer Key
Dim csecret = "56789" '// Consumer Secret
Dim tkey = "43210" '// Token ID
Dim tsecret = "98765" '// Token Secret
Dim Signature = OAuthBase.GenerateSignature(url, ckey, csecret, tkey, tsecret, "POST", timestamp, nonce)
If (Signature.Contains("+")) Then
Signature = Signature.Replace("+", "%3D")
End If
Dim header As String = "Authorization: OAuth "
header += "oauth_signature=""" & Signature & ""","
header += "oauth_version=""1.0"","
header += "oauth_nonce=""" & nonce & ""","
header += "oauth_signature_method=""HMAC-SHA1"","
header += "oauth_consumer_key=""" & ckey & ""","
header += "oauth_token=""" & tkey & ""","
header += "oauth_timestamp=""" & timestamp & ""","
header += "realm=""xxxxxx"""
Thanks for your time.

The publicly available documentation for the library you are using only creates signatures in SHA1
see https://developer.tracesmart.co.uk/smartlink/example/vbnet-oauth-library for the code
You could take that and adapt it to use SHA256
System.Security.Cryptography contains an SHA256 class so the work shouldn't be too effortful.
I made the SHA1 -> SHA256 change for my node based library with just two changes. Your effort should be relatively the same.

Related

.NET Google API access token failing with no refresh token specified

I am trying to set up a class that can wrap around the .NET Google API so that I can use an Access Token that I have previously obtained to access a user's Google Drive. As of right now, I am just trying to get it to work so that I do not require a Refresh Token (more on that in a second). The ultimate goal is for somebody to go through a web page I have set up to authenticate where I obtain both an Access Token and a Refresh Token by directly calling to the Google Rest API (which I store in a database). They can then request to upload/download files onto their Drive on a different page which will first obtain the appropriate information from the database and then use the .NET Google API Library when accessing Drive.
However, when I attempt to access their Drive I get the the following error:
The access token has expired and could not be refreshed. Errors: refresh error, refresh error, refresh error
I know that the Access Token is valid because I obtain it only seconds earlier during my testing. Here is my code for setting up the Drive Service:
' NOTE: Code altered for brevity
Public Sub Initialize(accessToken As String)
' Set up the client secret information based on the default constants
Dim clientSecrets As New ClientSecrets()
clientSecrets.ClientId = DEFAULT_CLIENT_ID
clientSecrets.ClientSecret = DEFAULT_CLIENT_SECRET
' Set up a token based on the token data we got
' NOTE: Is it OK to leave some strings as NULL?
Dim token As New Responses.TokenResponse()
token.AccessToken = accessToken
token.RefreshToken = ""
token.TokenType = "Bearer"
token.IssuedUtc = DateTime.Now
token.ExpiresInSeconds = 3600
token.Scope = "drive"
token.IdToken = ""
' Set up a flow for the user credential
Dim init As New GoogleAuthorizationCodeFlow.Initializer()
init.ClientSecrets = clientSecrets
init.Scopes = New String() {DriveService.Scope.Drive}
init.Clock = Google.Apis.Util.SystemClock.Default
' Set up everything else and initialize the service
Dim baseInit As New BaseClientService.Initializer()
baseInit.HttpClientInitializer = New UserCredential(New GoogleAuthorizationCodeFlow(init), "user", token)
baseInit.ApplicationName = APP_NAME
_service = New DriveService(baseInit)
End Sub
Shortly after that, I then use the following code to request a folder so I can check to see if it exists or not.
Private Function GetDriveFolder(folderPath As String, ByRef folderIds As String(), Optional createMissingFolders As Boolean = False, Optional parentFolderId As String = "root") As Data.File
Dim creatingFolderPath As Boolean = False
Dim currentFolder As Data.File = Nothing
Dim folderPathSplit As String() = folderPath.Replace("/", "\").Trim("\").Split("\")
Dim folderIdList As New List(Of String)
folderIds = {}
' Loop through each folder in the path and seek each out until we reach the end
For x As Integer = 0 To folderPathSplit.Length - 1
Dim result As FileList = Nothing
If Not creatingFolderPath Then
' Build a list request which we will use to seek out the next folder
Dim request As FilesResource.ListRequest = _service.Files.List()
request.Q = "mimeType='application/vnd.google-apps.folder' and name='" & folderPathSplit(x) & "'"
If currentFolder Is Nothing Then
request.Q &= " and '" & EscapeDriveValue(parentFolderId) & "' in parents"
Else
request.Q &= " and '" & EscapeDriveValue(currentFolder.Id) & "' in parents"
End If
request.Spaces = "drive"
request.Fields = "files(id, name)"
' Execute the search, we should only get a single item back
' NOTE: Error thrown on this request
result = request.Execute()
End If
' So on.....
So, I'm just trying to get it to work with only the Access Token for the time being because if it ends up getting refreshed I'll need to know so that I can update my database. However, if I do include the Refresh Token I get the following error:
Error:"unauthorized_client", Description:"Unauthorized", Uri:""
I'm guessing this has something to do with the way I have configured my application through the Dev Console but if I authenticate through the Google API Library by having it launch a browser to get my credentials everything works fine. So, I'm really not sure where to go from here as I haven't found anybody having similar problems and the guides don't cover specifying your own Access Token.
Also, as a quick note this is the URL I am using when having the user authenticate:
String.Format("https://accounts.google.com/o/oauth2/v2/auth?client_id={0}&state={1}&redirect_uri={2}&scope=https%3A%2F%2Fwww.googleapis.com%2Fauth%2Fdrive&access_type=offline&include_granted_scopes=true&prompt=select_account%20consent&response_type=code", GOOGLEAPI_CLIENTID, validateState, redirectUri)
Thanks for the help!
If you have an access-token then the simplest way to create a google credential is to use the GoogleCredential.FromAccessToken() method passing in your access token.
This returns you a GoogleCredential instance which you can use to set the HttpClientInitializer property when building the DriveService.
If you then still get an error when accessing the drive service, then it's likely there's something incorrect in how you are asking for the access-token.

DocuSign Embedded RequestRecipientToken - 500 internal Server Error

-Issue Resolved
On Live accounts that Use Embedded Signing, The Account Manager will need to either disable In Session or apply the accounts X.509 Certificate.
There is no way to bypass without the DocuSign Account Managers/Customer Support making updates to non forward facing settings.
-Using SOAP API in a VB.NET application.
I have recently moved our application to live after endless testing on the staging environment. Everything is working as expected except when I get too opening the recipient signature page.
When I make the RequestRecipientToken call I receive the error "One or both of Username and Password are invalid."
The API log give me 00_Internal Server Error_RequestRecipientToken.txt
the log doesn't really give me any info just shows that call.
I know this all works on staging, and I have tried to have all my account settings the same on both environments.
After looking all over I saw that X509 Certificate was recommended, so I added this last line in my DSAPI
-update code:
Protected Overrides Function GetWebRequest(uri As Uri) As WebRequest
IntegratorKey = SettingsHelper.sIntegrationKey
Password = SettingsHelper.sAPIPassword
Username = SettingsHelper.sAPIUserName
Dim r As System.Net.HttpWebRequest = MyBase.GetWebRequest(uri)
r.Headers.Add("X-DocuSign-Authentication", "<DocuSignCredentials><Username>" & Username & "</Username><Password>" & Password & "</Password><IntegratorKey>" & IntegratorKey & "</IntegratorKey></DocuSignCredentials>")
Dim store As X509Store = New X509Store(StoreName.My, StoreLocation.CurrentUser)
store.Open(OpenFlags.ReadOnly)
Dim certs As X509Certificate2Collection = store.Certificates.Find(X509FindType.FindByIssuerDistinguishedName, <{OUR VALUE}>, False)
Dim cert As New X509Certificate2
If certs.Count > 0 Then
cert = certs(0)
Dim securityToken = New X509SecurityToken(cert)
r.ClientCertificates.Add(securityToken.Certificate)
End If
store.Close()
Return r
End Function
This did not help.
Any help would be appreciated.

"IF" code is not working inside for each?

so im learning to use socket and thread things in the networking software. so far, the software (which is not created by me) is able to chat in multiple group, but i'm tasked to allow user to code whisper feature. However, im stuck in the coding area, which im sure will work if the "if" function work inside "for each" function, anyhow here is my code mainly
Private clientCollection As New Hashtable()
Private usernameCollection As New Hashtable()
clientCollection.Add(clientID, CData)
usernameCollection.Add(clientID, username)
oh and before i forgot, the code above and below is on the server form page
on the client side, i write the code:
writer.write("PMG" & vbnewline & txtReceiverUsername & Message)
then next is the checking part on the server reading the message:
ElseIf message.Substring(0, 3) = "PMG" Then
'filter the message, check who to send to
Dim newMessage As String = message.Substring(3)
Dim messagearray As String() = newMessage.Split(vbNewLine)
Dim receiver As String = messagearray(1)
'0 = "", 1 = receiver, 2 = message
as i write before, clientcollection contain (clientID , connection data*) and usernamecollection contain (clientID, username). In my case, i only have the username data, and i need to trace it until the connection data on clientcollection hash table.
'find realid from usernamecollection, then loop clientcollection
Dim clientKey As String = 0
For Each de As DictionaryEntry In usernameCollection
'''''
'this if part Is Not working
If de.Value Is receiver Then
clientKey = de.Key
End If
'''''
Next de
'match objKey with clientcollection key
For Each dec As DictionaryEntry In clientCollection
If dec.Key = clientKey Then
Dim clients As ClientData = dec.Value
If clients.structSocket.Connected Then
clients.structWriter.Write("PMG" & messagearray(2))
End If
End If
Next dec
End If
so, how do i know that the if part is the wrong one? simply i tried these code before the "next de" code
For Each client As ClientData In clientCollection.Values
If client.structSocket.Connected Then
client.structWriter.Write("PMG" & "receiver:" & messagearray(1))
client.structWriter.Write("PMG" & "loop username: " & de.Value)
client.structWriter.Write("PMG" & "loop key: " & de.Key)
client.structWriter.Write("PMG" & "receiver key:" & clientKey)
End If
Next
the code allow me to check the de.key and de.value. they were correct, however the only thing that did not work is the code inside the "if" area.
Can anyone suggest other code maybe beside "if de.key = receiver"? I've also tried using the if de.key.equal(receiver) and it did not work too

Uploading a file to Azure Blob Storage using VBA and MS XMLHTTP

I've been trying to upload file to Azure storage using VBA in Microsoft Access but so far without success.
I have had a good search around and have found some code which looks promising but I can't get it to work. Seems like many others have been looking for a similar solution or help with working with Azure from VBA.
This is the code;
Private Function pvPostFile(sUrl As String, sFileName As String, Optional ByVal bAsync As Boolean) As String
Const STR_BOUNDARY As String = "3fbd04f5-b1ed-4060-99b9-fca7ff59c113"
Dim nFile As Integer
Dim baBuffer() As Byte
Dim sPostData As String
'--- read file
nFile = FreeFile
Open sFileName For Binary Access Read As nFile
If LOF(nFile) > 0 Then
ReDim baBuffer(0 To LOF(nFile) - 1) As Byte
Get nFile, , baBuffer
sPostData = StrConv(baBuffer, vbUnicode)
End If
Close nFile
'--- prepare body
sPostData = "--" & STR_BOUNDARY & vbCrLf & _
"Content-Disposition: form-data; name=""uploadfile""; filename=""" & Mid$(sFileName, InStrRev(sFileName, "\") + 1) & """" & vbCrLf & _
"Content-Type: application/octet-stream" & vbCrLf & vbCrLf & _
sPostData & vbCrLf & _
"--" & STR_BOUNDARY & "--"
'--- post
With CreateObject("Microsoft.XMLHTTP")
.Open "POST", sUrl, bAsync
.SetRequestHeader "Content-Type", "multipart/form-data; boundary=" & STR_BOUNDARY
.Send pvToByteArray(sPostData)
If Not bAsync Then
pvPostFile = .ResponseText
End If
End With
End Sub
Private Function pvToByteArray(sText As String) As Byte()
pvToByteArray = StrConv(sText, vbFromUnicode)
End Function
(Thanks to - https://wqweto.wordpress.com/2011/07/12/vb6-using-wininet-to-post-binary-file/)
When I try this code using my azure storage URL in the form
https://XXXXX.blob.core.windows.net/
and a filename (C:\Temp\Test.txt) I get the following error;
<?xml version="1.0" encoding="utf-8"?><Error><Code>UnsupportedHttpVerb</Code><Message>The resource doesn't support specified Http Verb.
I suspect there's a problem in the header or post data rather than the VBA and this is not really my area.
Any help greatly appreciated.
I came across this post as I'm searching the same answer for uploading images to Azure Blob Storage. I took me 2 days to get the answer. And the code posted above did help me to partly solve the problem.
I would like to post my solution here in case anyone else is looking for the same answer.
Before you can use the code below, you need to get the Shared Access Signature (SAS) from your Azure portal (manage panel). You should be able to google the answers on this.
Public Sub UploadAfIle(sUrl As String, sFileName As String)
Dim adoStream As Object
Set adoStream = CreateObject("ADODB.Stream")
adoStream.Mode = 3 ' read write
adoStream.Type = 1 ' adTypeBinary
adoStream.Open
adoStream.LoadFromFile (sFileName)
With CreateObject("Microsoft.XMLHTTP")
adoStream.Position = 0
.Open "PUT", sUrl, False
.setRequestHeader "Content-Length", "0" 'this is not a must
.setRequestHeader "x-ms-blob-type", "BlockBlob"
.Send adoStream.Read(adoStream.Size)
End With
Set adoStream = Nothing
End Sub
sURL is a URL looks like (I'm in China so the Host is different): https://myaccount.blob.core.chinacloudapi.cn/products/newimagename.jpg?sv=2016-05-31&ss=bfpq&srt=dco&sp=rydlscup&se=2017-07-30T18:40:26Z&st=2017-07-28T10:40:26Z&spr=https&sig=mJgDyECayITp0ivVrD4Oug%2Bz%2chN7Wpo2nNtcn0pYRCU%4d
The one bolded is the SAS token you generated from Azure.
Worth noting the format of the sUrl in SiliconXu's answer is made up of 3 parts, I didn't realise at first so got a sore head for a while!!
1) Azure blob container URL (from the properties in the Storage Explorer)
2) the filename (this is the part I omitted by mistake)
3) Shared Access Signature
So is built like this
sURL = destination_folder & "/" & local_file_name & "?" & conn_SAS
I don't have the reputation require to comment directly below that answer
Great code though, as soon as I worked out the format of the sURL it worked like a dream
Azure Storage Service uses private key authentication. Since VBA runs on the end user's machine you are exposing yourself to a whole slew of risks associated with that key getting into the wild. I would recommend rethinking the whole premise of going directly from VBA to Azure Storage and utilize your own WebAPI to handle storing data to Blob.
This would have the dual benefit of:
1) making it easier to integrate with from VBA and
2) protecting your Azure Storage private key behind a component of your solution that doesn't get deployed to the end user's machine.

Calculating the b- value in a DKIM string in VB.NET

I am trying to calculate the b= string in the DKIM-Signature for a e-mail message. However I am getting no luck with the methodes available.
I have created a RSACryptoServiceProvider and imported a private key using the fromXMLString option.
creating a signature from a hash and verifying it works fine.
Dim hashdata As Byte() = Encoding.ASCII.GetBytes(headers.ToString)
Dim signature As Byte() = RSA.SignData(hashdata, CryptoConfig.MapNameToOID("SHA256"))
If RSA.VerifyData(hashdata, "SHA256", signature) = True Then
headers.AppendLine("Signature: RSA-SHA256 ")
Else
headers.AppendLine("Signature: None")
End If
The above code verifies the signature, but the DKIM does not pass valid as a whole.
I have seen a example of bouncyCastle "
ISigner sig = SignerUtilities.GetSigner("SHA256WithRSAEncryption");
But I cant use this in my programming.
Can someone help me on the way on how to properly sign a canonicalized header for dkim purpose ?