How to generate a hash for my Android app? - c#

I'm using this guide to implement an autocomplete funcionality in an app I'm working on, but when I try to test it in different computers it returns me a different hash https://www.c-sharpcorner.com/article/verify-otp-automatically-in-android-without-sms-read-permission-using-xamarin-fo/
The helper class used is the following:
using System.Text;
using Android.Content;
using Android.Content.PM;
using Android.Util;
using Java.Security;
using Java.Util;
namespace InteliMobile.App.Droid.Service
{
public class AppHashKeyHelper
{
private static string HASH_TYPE = "SHA-256";
private static int NUM_HASHED_BYTES = 9;
private static int NUM_BASE64_CHAR = 11;
private static string GetPackageSignature(Context context)
{
var packageManager = context.PackageManager;
var signatures = packageManager.GetPackageInfo(context.PackageName, PackageInfoFlags.Signatures).Signatures;
return signatures.First().ToCharsString();
}
public static string GetAppHashKey(Context context)
{
string keystoreHexSignature = GetPackageSignature(context);
string appInfo = context.PackageName + " " + keystoreHexSignature;
try
{
var messageDigest = MessageDigest.GetInstance(HASH_TYPE);
messageDigest.Update(Encoding.UTF8.GetBytes(appInfo));
byte[] hashSignature = messageDigest.Digest();
hashSignature = Arrays.CopyOfRange(hashSignature, 0, NUM_HASHED_BYTES);
string base64Hash = Android.Util.Base64.EncodeToString(hashSignature, Base64Flags.NoPadding | Base64Flags.NoWrap);
base64Hash = base64Hash.Substring(0, NUM_BASE64_CHAR);
return base64Hash;
}
catch (NoSuchAlgorithmException e)
{
return null;
}
}
}
}
How can I get the hash without using a bash script, since the server runs in a Windows machine? Is it safe to deploy the app to production with the helper class in it?

You don't compute the hash client side. It's sent from the server, and the instructions to do so are at https://developers.google.com/identity/sms-retriever/verify#computing_your_apps_hash_string
You don't do it in code at all, you do it via command line tools.

Related

How to convert azure vision output in string Json to previous object?

I have converted the input image into OCRResults by using these codes.
https://learn.microsoft.com/en-us/azure/cognitive-services/computer-vision/quickstarts-sdk/client-library?tabs=visual-studio&pivots=programming-language-csharp
using System;
using System.Collections.Generic;
using Microsoft.Azure.CognitiveServices.Vision.ComputerVision;
using Microsoft.Azure.CognitiveServices.Vision.ComputerVision.Models;
using System.Threading.Tasks;
using System.IO;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using System.Threading;
using System.Linq;
namespace ComputerVisionQuickstart
{
class Program
{
// Add your Computer Vision subscription key and endpoint
static string subscriptionKey = "PASTE_YOUR_COMPUTER_VISION_SUBSCRIPTION_KEY_HERE";
static string endpoint = "PASTE_YOUR_COMPUTER_VISION_ENDPOINT_HERE";
private const string READ_TEXT_URL_IMAGE = "https://raw.githubusercontent.com/Azure-Samples/cognitive-services-sample-data-files/master/ComputerVision/Images/printed_text.jpg";
static void Main(string[] args)
{
Console.WriteLine("Azure Cognitive Services Computer Vision - .NET quickstart example");
Console.WriteLine();
ComputerVisionClient client = Authenticate(endpoint, subscriptionKey);
// Extract text (OCR) from a URL image using the Read API
ReadFileUrl(client, READ_TEXT_URL_IMAGE).Wait();
}
public static ComputerVisionClient Authenticate(string endpoint, string key)
{
ComputerVisionClient client =
new ComputerVisionClient(new ApiKeyServiceClientCredentials(key))
{ Endpoint = endpoint };
return client;
}
public static async Task ReadFileUrl(ComputerVisionClient client, string urlFile)
{
Console.WriteLine("----------------------------------------------------------");
Console.WriteLine("READ FILE FROM URL");
Console.WriteLine();
// Read text from URL
var textHeaders = await client.ReadAsync(urlFile);
// After the request, get the operation location (operation ID)
string operationLocation = textHeaders.OperationLocation;
Thread.Sleep(2000);
// Retrieve the URI where the extracted text will be stored from the Operation-Location header.
// We only need the ID and not the full URL
const int numberOfCharsInOperationId = 36;
string operationId = operationLocation.Substring(operationLocation.Length - numberOfCharsInOperationId);
// Extract the text
ReadOperationResult results;
Console.WriteLine($"Extracting text from URL file {Path.GetFileName(urlFile)}...");
Console.WriteLine();
do
{
results = await client.GetReadResultAsync(Guid.Parse(operationId));
}
while ((results.Status == OperationStatusCodes.Running ||
results.Status == OperationStatusCodes.NotStarted));
// Display the found text.
Console.WriteLine();
var textUrlFileResults = results.AnalyzeResult.ReadResults;
foreach (ReadResult page in textUrlFileResults)
{
foreach (Line line in page.Lines)
{
Console.WriteLine(line.Text);
}
}
Console.WriteLine();
}
}
}
If I converting the output from the azure vision into json.Is any possibilities convert the json to previous object?

Azure Function Runs Locally But Not On Azure

My function is running locally but when I publish it to Azure it is erroring.
The error is
Value cannot be null. Parameter name: format
Googling this seems to suggest the input to the function is wrong but I am posting the exact same JSON that allows it to run locally.
I am lost to how I fix this. Any ideas?
Code below
using System;
using System.Configuration;
using System.Net;
using System.Net.Http;
using System.Security.Cryptography;
using System.ServiceModel.Description;
using System.Text;
using System.Threading.Tasks;
using Microsoft.Azure.WebJobs;
using Microsoft.Azure.WebJobs.Extensions.Http;
using Microsoft.Azure.WebJobs.Host;
using Microsoft.Xrm.Sdk;
using Microsoft.Xrm.Sdk.Client;
using Microsoft.Xrm.Sdk.Query;
using Newtonsoft.Json;
using Microsoft.Extensions.Logging;
namespace MyFunction
{
public static class Login
{
[FunctionName("Login")]
public static async Task<HttpResponseMessage> Run([HttpTrigger(AuthorizationLevel.Function, "get", "post", Route = null)]HttpRequestMessage req, ILogger log)
{
Boolean websiteEnabled = false;
Guid contactId = new Guid();
log.LogInformation("C# HTTP trigger function processed a request.");
dynamic data = await req.Content.ReadAsAsync<object>();
string username = data?.username;
string password = data?.password;
string passwordHash = "";
User user = new User();
OrganizationServiceProxy _serviceProxy;
IOrganizationService _service;
ClientCredentials clientCredentials = new ClientCredentials();
clientCredentials.UserName.UserName = ConfigurationManager.AppSettings["OrganisationUsername"];
clientCredentials.UserName.Password = ConfigurationManager.AppSettings["OrganisationPassword"];
Uri organisationUri = new Uri(String.Format(ConfigurationManager.AppSettings["OrganisationURL"]));
Uri realm = new Uri(String.Format(ConfigurationManager.AppSettings["OrganisationURL"]));
using (_serviceProxy = new OrganizationServiceProxy(organisationUri, realm, clientCredentials, null))
{
_serviceProxy.EnableProxyTypes();
_service = (IOrganizationService)_serviceProxy;
QueryByAttribute querybyattribute = new QueryByAttribute("contact");
querybyattribute.ColumnSet = new ColumnSet("cbob_websitepassword","cbob_websiteenabled","contactid","fullname", "parentcustomerid");
querybyattribute.Attributes.AddRange("emailaddress1");
querybyattribute.Values.AddRange(username);
EntityCollection retrieved = _service.RetrieveMultiple(querybyattribute);
if(retrieved.Entities.Count == 1)
{
passwordHash = retrieved.Entities[0].GetAttributeValue<String>("cbob_websitepassword");
websiteEnabled = retrieved.Entities[0].GetAttributeValue<Boolean>("cbob_websiteenabled");
contactId = retrieved.Entities[0].GetAttributeValue<Guid>("contactid");
user.Account = retrieved.Entities[0].GetAttributeValue<EntityReference>("parentcustomerid").Name.ToString();
user.Email = username;
user.LoggedInUser = retrieved.Entities[0].GetAttributeValue<String>("fullname");
user.AccountID = retrieved.Entities[0].GetAttributeValue<EntityReference>("parentcustomerid").Id.ToString();
user.BookingID = retrieved.Entities[0].Id.ToString();
} else
{
return req.CreateResponse(HttpStatusCode.BadRequest, "Not allowed");
}
}
Boolean hash = bCryptHash(passwordHash, contactId.ToString() + "-" + password);
Console.WriteLine(hash);
if (!websiteEnabled)
{
return req.CreateResponse(HttpStatusCode.BadRequest, "Not allowed");
}
if (hash)
{
string output = JsonConvert.SerializeObject(user).ToString();
return req.CreateResponse(HttpStatusCode.OK, output);
} else
{
return req.CreateResponse(HttpStatusCode.BadRequest, "Not allowed");
}
}
public static Boolean bCryptHash(string hash, string submitted)
{
Boolean hashPassword = BCrypt.Net.BCrypt.Verify(submitted,hash);
return hashPassword;
}
public static String sha256_hash(string value)
{
StringBuilder Sb = new StringBuilder();
using (var hash = SHA256.Create())
{
Encoding enc = Encoding.UTF8;
Byte[] result = hash.ComputeHash(enc.GetBytes(value));
foreach (Byte b in result)
Sb.Append(b.ToString("x2"));
}
return Sb.ToString();
}
}
}
Uri organisationUri = new Uri(String.Format(ConfigurationManager.AppSettings["OrganisationURL"]));
Uri realm = new Uri(String.Format(ConfigurationManager.AppSettings["OrganisationURL"]));
My guess is that one or both of those lines may be the problem. You are using String.Format here where the first parameter is the format parameter. The AppSettings you are providing for that parameter seem to be unavailable. Make sure you have those configuration values available when you deploy your function.
Additionally: If you don't provide any objects to the String.Format that get inserted in the String, why are you using it at all?
Make sure you have added those local app settings (i.e OrganisationUsername and so on in local.settings.json file) to Application settings. Find it in Azure portal, Platform features> Application settings. When we publish Function project to Azure, it's by design that content in local.settings.json is not published because it's designed for local dev.
When we publish Functions with VS, there's a friendly dialog to update Application settings.

Wopi Office Online proof keys process

I'm trying to Verifying that requests originate from Office Online by using proof keys
i'm implementing the wopi host with nodejs, and there are samples of code in the link above that implements the proof keys process using .NET
so i'm using the edge package to be able to run the .NET code with nodejs.
the problem is that the code is running fine, but it always returning that the proof keys in the request are not valid even when the requests are coming from the wopi client.
explanation: there are 3 functions:
validateProofKey - the main function - get all the requierd params to validate the proof key and return bool if they are valid using the functions : constructProofKey and TryProofkeyVerification
constructProofKey - declare .NET function (constructProofKey from sample code ) , run it and return the result of the constructed proofkey
TryProofkeyVerification - declare .NET function (TryProofkeyVerification from .NET sample code), run it and return the Boolean result
the code :
static async validateProofKey(access_token: string, request_url: string, X_WOPI_TimeStamp: string, X_WOPI_Proof: string, X_WOPI_Proof_old: string): Promise<boolean> {
//get public key provided in WOPI discovery:
if (!wopiDiscovery) { wopiDiscovery = await this.getWopiDiscovery() }
const public_Keys: iWopiDiscoveryProofKey = wopiDiscovery["wopi-discovery"]["proof-key"];
const public__Key: string = public_Keys.value;
const old_public_Key: string = public_Keys.oldvalue;
this.printProofkeyArgs(access_token, request_url, X_WOPI_TimeStamp, X_WOPI_Proof, X_WOPI_Proof_old, public__Key, old_public_Key, modulus_b64, exp_b64);
//1. Create the expected value of the proof headers.
let expectedProofKey: Buffer = await this.constructProofKey(access_token, request_url, X_WOPI_TimeStamp);
//2.Use the public key provided in WOPI discovery to decrypt the proof provided in the X-WOPI-Proof header.
const verified: boolean = await this.TryProofkeyVerification(expectedProofKey, X_WOPI_Proof, public__Key) ||
await this.TryProofkeyVerification(expectedProofKey, X_WOPI_Proof_old, public__Key) ||
await this.TryProofkeyVerification(expectedProofKey, X_WOPI_Proof, old_public_Key)
return verified;
}
constructProofKey
private static constructProofKey(access_token: string, request_url: string, X_WOPI_TimeStamp: string): Promise<Buffer> {
return new Promise((resolve, reject) => {
const proofParams = {
access_token: access_token,
request_url: request_url,
X_WOPI_TimeStamp: X_WOPI_TimeStamp
}
const constructProofKey = edge.func(`
using System.Threading.Tasks;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Security.Cryptography;
using System.Text;
public class Startup
{
public async Task<object> Invoke(dynamic proofParams)
{
return Helper.constructProofKey(proofParams);
}
}
static class Helper
{
public static byte[] constructProofKey(dynamic proofParams)
{
// Encode values from headers into byte[]
long timestamp = Convert.ToInt64(proofParams.X_WOPI_TimeStamp);
var accessTokenBytes = Encoding.UTF8.GetBytes(proofParams.access_token);
var hostUrlBytes = Encoding.UTF8.GetBytes(proofParams.request_url.ToUpperInvariant());
var timeStampBytes = EncodeNumber(timestamp);
// prepare a list that will be used to combine all those arrays together
List < byte > expectedProof = new List<byte>(
4 + accessTokenBytes.Length +
4 + hostUrlBytes.Length +
4 + timeStampBytes.Length);
expectedProof.AddRange(EncodeNumber(accessTokenBytes.Length));
expectedProof.AddRange(accessTokenBytes);
expectedProof.AddRange(EncodeNumber(hostUrlBytes.Length));
expectedProof.AddRange(hostUrlBytes);
expectedProof.AddRange(EncodeNumber(timeStampBytes.Length));
expectedProof.AddRange(timeStampBytes);
// create another byte[] from that list
byte[] expectedProofArray = expectedProof.ToArray();
return expectedProofArray;
}
private static byte[] EncodeNumber(long value)
{
return BitConverter.GetBytes(value).Reverse().ToArray();
}
}
`)
constructProofKey(proofParams, (error, result) => {
if (error) {
reject(error);
}
resolve(result);
});
})
}
TryProofkeyVerification
private static TryProofkeyVerification(expectedProofKey: Buffer, private_proofkey: string, public_proofkey: string): Promise<boolean> {
return new Promise((resolve, reject) => {
const proofParams = {
expectedProofKey: expectedProofKey,
private_proofkey: private_proofkey,
public_proofkey: public_proofkey
}
//declare .NET code
const TryVerification = edge.func(`
using System.Threading.Tasks;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Security.Cryptography;
using System.Text;
public class Startup
{
public async Task<object> Invoke(dynamic proofParams)
{
return Helper.TryVerification(proofParams);
}
}
static class Helper
{
public static bool TryVerification(dynamic proofParams)
{
byte[] expectedProofKey = (byte[])proofParams.expectedProofKey;
using(RSACryptoServiceProvider rsaAlg = new RSACryptoServiceProvider())
{
byte[] publicKey = Convert.FromBase64String(proofParams.public_proofkey);
byte[] signedProofBytes = Convert.FromBase64String(proofParams.private_proofkey);
try
{
rsaAlg.ImportCspBlob(publicKey);
return rsaAlg.VerifyData(expectedProofKey, "SHA256", signedProofBytes);
}
catch(FormatException)
{
Console.WriteLine("Format Exception");
return false;
}
catch(CryptographicException e)
{
Console.WriteLine("CryptographicException Exception");
return false;
}
}
}
}
`);
//Invoke .NET code
TryVerification(proofParams, (error, result) => {
if (error) {
reject(error);
}
resolve(result);
});
})
}
NOTE - I've already log the parameters to console to make sure the parameters transferred correctly through all the process

Hadoop task is cancelled due to task timeout

I am writing a C# mapreduce program that runs on the cluster. The system returns an error of
System.Threading.Tasks.Task
The task is cancelled after a timeout of 32 milliseconds. The data is pretty huge .I even changed the data size to check but the error still occurs, so I am assuming it is not due to the data size.
Is there a way to change the task timeout of 32 milliseconds.
I am using Azure, Visual studio 2013 and a cluster with 4 nodes.
The system aggregate exception occured in mscorlib.dll
using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using System.Text;
using System.Xml.Linq;
using System.Threading;
using Microsoft.Hadoop.MapReduce;
using Microsoft.WindowsAzure.Management.HDInsight;
using System.IO;
using System.Security.Cryptography.X509Certificates;
using Microsoft.Hadoop.Client;
namespace StackExtractor
{
//Our Mapper that takes a line of XML input and spits out the {OwnerUserId,ParentId,Score}
//i.e, {User,Question,Weightage}
public class UserQuestionsMapper : MapperBase
{
public override void Map(string inputLine, MapperContext context)
{
try
{
var obj = XElement.Parse(inputLine);
var postType = obj.Attribute("PostTypeId");
if (postType != null && postType.Value == "2")
{
var owner = obj.Attribute("OwnerUserId");
var parent = obj.Attribute("ParentId");
// Write output data. Ignore records will null values if any
if (owner != null && parent != null)
{
context.EmitLine(string.Format("{0},{1}", owner.Value, parent.Value));
}
}
}
catch
{
//Ignore this line if we can't parse
}
}
}
//Our Extraction Job using our Mapper
public class UserQuestionsExtractionJob : HadoopJob<UserQuestionsMapper>
{
public override HadoopJobConfiguration Configure(ExecutorContext context)
{
var config = new HadoopJobConfiguration();
config.DeleteOutputFolder = true;
config.InputPath = "/input/recommender";
config.OutputFolder = "/output/recommender";
return config;
}
}
//Driver that submits this to the cluster in the cloud
//And will wait for the result. This will push your executables to the Azure storage
//and will execute the command line in the head node (HDFS for Hadoop on Azure uses Azure storage)
public class Driver
{
public static void Main()
{
try
{
var azureCluster = new Uri("https://name r.azurehdinsight.net:563");
const string clusterUserName = "****";
const string clusterPassword = "****";
// This is the name of the account under which Hadoop will execute jobs.
// Normally this is just "Hadoop".
const string hadoopUserName = "Hadoop";
// Azure Storage Information.
const string azureStorageAccount = "name.blob.core.windows.net";
const string azureStorageKey = "id;
const string azureStorageContainer = "namecontainer";
const bool createContainerIfNotExist = true;
Console.WriteLine("Connecting : {0} ", DateTime.Now);
var hadoop = Hadoop.Connect(azureCluster,
clusterUserName,
hadoopUserName,
clusterPassword,
azureStorageAccount,
azureStorageKey,
azureStorageContainer,
createContainerIfNotExist);
Console.WriteLine("Starting: {0} ", DateTime.Now);
var result = hadoop.MapReduceJob.ExecuteJob <UserQuestionsExtractionJob>();
var info = result.Info;
Console.WriteLine("Done: {0} ", DateTime.Now);
Console.WriteLine("\nInfo From Server\n----------------------");
Console.WriteLine("StandardError: " + info.StandardError);
Console.WriteLine("\n----------------------");
Console.WriteLine("StandardOut: " + info.StandardOut);
Console.WriteLine("\n----------------------");
Console.WriteLine("ExitCode: " + info.ExitCode);
}
catch (Exception ex)
{
Console.WriteLine("Error: {0} ", ex.StackTrace.ToString(CultureInfo.InvariantCulture));
}
Console.WriteLine("Press Any Key To Exit..");
Console.ReadLine();
}
}
}

Generating msi transform using c#

I am creating a cutomization software which will do all the standardization to a mst file.
Below is the code of class that will change product name and genrate transform.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using WindowsInstaller;
using System.Data;
namespace Automation
{
class CustomInstaller
{
public CustomInstaller()
{
}
public Record getInstaller(string msiFile,MsiOpenDatabaseMode mode,string query)
{
Type type = Type.GetTypeFromProgID("WindowsInstaller.Installer");
Installer inst = (Installer)Activator.CreateInstance(type);
Database db = inst.OpenDatabase(msiFile, mode);
WindowsInstaller.View view = db.OpenView(query);
view.Execute(null);
Record record = view.Fetch();
db.Commit();
return record;
}
public bool generateTrans(string file1, string file2,string transName)
{
Type type = Type.GetTypeFromProgID("WindowsInstaller.Installer");
Installer inst = (Installer)Activator.CreateInstance(type);
Database db1 = inst.OpenDatabase(file1, MsiOpenDatabaseMode.msiOpenDatabaseModeReadOnly);
try
{
Database db2 = inst.OpenDatabase(file2, MsiOpenDatabaseMode.msiOpenDatabaseModeReadOnly);
return db2.GenerateTransform(db1, transName);
}
catch (Exception e) { }
return false;
}
public int editTransform(string msiFile, MsiOpenDatabaseMode mode, string query)
{
Type type = Type.GetTypeFromProgID("WindowsInstaller.Installer");
Installer inst = (Installer)Activator.CreateInstance(type);
Database db = inst.OpenDatabase(msiFile, mode);
WindowsInstaller.View view = db.OpenView(query);
view.Execute(null);
db.Commit();
int o=(int)db.DatabaseState;
db = null;
inst = null;
type = null;
return 1;
}
}
}
First editTransform() is called which will create a copy of original msi and do some changes in it, then generateTrans() is called which will get difference detween two msi files and create a transform file.
Now issue is when genrateTrans() is called, then it goes to catch block of it as inst.OpenDatabase return "MSI Api Error".
It seems to me that the copy of file crated by editTransform is still locked by it and is not available for use for generateTrans() menthod.
Please help here.
PS: mode used for edit transform is transact.
Instead of doing the COM Interop, checkout the far superior interop library ( Microsoft.Deployment.WindowsInstaller ) found in Windows Installer XML Deployment Tools Foundation. You'll find it much easier to use.
using System;
using System.IO;
using Microsoft.Deployment.WindowsInstaller;
namespace ConsoleApplication1
{
class Program
{
const string REFERENCEDATABASE = #"C:\orig.msi";
const string TEMPDATABASE = #"C:\temp.msi";
const string TRANSFORM = #"c:\foo.mst";
static void Main(string[] args)
{
File.Copy(REFERENCEDATABASE, TEMPDATABASE, true);
using (var origDatabase = new Database(REFERENCEDATABASE, DatabaseOpenMode.ReadOnly))
{
using (var database = new Database(TEMPDATABASE, DatabaseOpenMode.Direct))
{
database.Execute("Update `Property` Set `Property`.`Value` = 'Test' WHERE `Property`.`Property` = 'ProductName'");
database.GenerateTransform(origDatabase, TRANSFORM);
database.CreateTransformSummaryInfo(origDatabase, TRANSFORM, TransformErrors.None, TransformValidations.None);
}
}
}
}
}

Categories