Sample X509Certificate2 RawData to use for unit tests? - encryption

I'm working on some RSA encryption/decryption unit tests and all of my functions require some certificates. I'm using dependency injection for these certs so for my unit tests, I'd like to just get some sample dummy (but functional) certificate to test my encryption/decryption library. I'd like to do this by hardcoding the RawData of valid certificate in my unit tests' SetUp method.
Where can I find something like this to put into my unit tests' SetUp method? Or how can I create this and pull this "raw data"? I'm not sure exactly what this "RawData" is. If somebody has something posted online (which would obviously be insecure, which is fine for my unit testing purposes), that would be preferable (from a lazy perspective) but I'm fine generating a cert and pulling this data as well.

Use .Export() instead of .RawData
When the X509Certificate2 has a private key within you can call:
var certBytes = certificateWithPrivateKey.Export(X509ContentType.Pkcs12);
Which returns a byte[] similar to .RawData, but it keeps the private key.
To store this in a unit test, you could just have a const string as Base64 of that data. Which you would get from:
var certAsString = Convert.ToBase64String(certBytes);
You can restore the key from this byte[] by constructing a X509Certificate2 with it:
var certificateCopy = new X509Certificate2(certBytes);
// Or from the string:
var certificateCopy2 = new X509Certificate2(Convert.FromBase64String(certAsString));

I don't understand it but this is what's going on...
I have a helper method that I call:
var cert = X509CertificateHelper.LoadCertificate(StoreName.My, StoreLocation.LocalMachine, "thumbprintgoeshere");
When I call this, cert is successfully populated and even HasPrivateKey is true. However, if I then do the following:
var cert2 = new X509Certificate2(cert.RawData);
then the resulting cert2 certificate, which is also what appears to be a valid certificate, has HasPrivateKey set to false. It appears that the RawData property "strips" out the private key (and yes, it's exportable - I have no problems creating a .pfx w/private key and importing it on another system and reproducing this behavior).
Now that I've discovered all of this, my solution is no longer to hardcode the RawData but instead to actually load up a certificate out of the certificate store - exactly what I was trying to avoid doing. If somebody has a better idea, please lay it on me. But until then, I'm calling this a failure and this is my end result. :-(

Related

Encrypting user passwords, save secret key to file

I'm trying to make secure keeping users passwords in database. After quick research I decided use ed25519_dalek library.
Important notice:
I plan use this encryption in actix website.
For now steps are simple:
save password in variable,
generate keys,
save secret and public passwords in file(for now),
encrypt password,
save password to database(skipping for now),
I'm stack in third step: saving keys to file.
To be honest I can write passwords to file, but can't read it.
My code below:
use std::io;
use std::io::{BufRead, Write};
use rand::rngs::OsRng;
use ed25519_dalek::{Keypair, PublicKey, Signature, Signer, Verifier};
use ed25519_dalek::{PUBLIC_KEY_LENGTH, SECRET_KEY_LENGTH, KEYPAIR_LENGTH, SIGNATURE_LENGTH};
let mut csprng = OsRng{};
let keypair: Keypair = Keypair::generate(&mut csprng);
let password: &[u8] = b"testing_password123!##$%";
let signature: Signature = keypair.sign(password);
assert!(keypair.verify(&password, &signature).is_ok());
For this moment my code works well. I'm getting signature and looks like values password and signature are the same.
I'm trying to deserialize keys:
let public_key_bytes: [u8; PUBLIC_KEY_LENGTH] = keypair.public.to_bytes();
let secret_key_bytes: [u8; SECRET_KEY_LENGTH] = keypair.secret.to_bytes();
let keypair_bytes: [u8; KEYPAIR_LENGTH] = keypair.to_bytes();
let signature_bytes: [u8; SIGNATURE_LENGTH] = signature.to_bytes();
After this, I want to save secret key and public key to different files. But for simplify we want to save only secret key.
My steps below:
use std::fs::File;
use std::io::prelude::*;
use std::path::Path;
let filename = "keys.txt";
let path = Path::new(filename);
let display = path.display();
let mut file = match File::create(&path) {
Err(why) => panic!("Couldn't create {}: {}", display, why),
Ok(file) => file,
};
match file.write_all(&secret_key_bytes) {
Err(why) => panic!("couldn't write to {}: {}", display, why),
Ok(_) => println!("successfully wrote to {}", display),
};
In this step I can write bytes to a file. But... The key has type [u8;32]. Using cat command showing strange things(I understand why).
But I can't read this file. Bytes can't be read like this.
After this entry is time for my question:
How can I change type of secret key [u8;32] to String or str?
My idea is:
Change datatype to String or str and then save to file.
Or maybe I do something wrong or simply is it better way to do this?
I need little push in right way :)
It is unsafe to encrypt and store passwords in a database. Moreover you are planning to store both public and private keys in files. The program requires it to be kept in reach for authenticating, so it won't be hard for someone to find the files with public and private keys. Anyone who have access to those files can access users' passwords including you.
The workaround is to generate a hash from the password and store it in the database. Hashing is a one way process of generating a string from an input string such that the inverse operation is impossible. So,the hash of the user input and the hash in the database is matched to authorize the user. There are a bunch of hashing functions available in RUST including the SHA-2 family hashing functions.
It is still insecure if you are just hashing the passwords and saving them in the database since the hashes of most common passwords and almost all possible words are already available in datasets named hash dictionaries and by using that, anyone who have access to your database can find the password. This technique is called dictionary attack. To prevent it, you can make the input string larger by concatenating with some random characters (salt) with the user input and
store the hash and the salt in the database.

How can the JsonProvider be used with URLs requiring authentication?

I want to do something very similar to what's shown in the docs for FSharp.Data:
The URL I'm requesting from though (TFS) requires client authentication. Is there any way I can provide this by propagating my Windows creds? I notice JsonProvider has a few other compile-time parameters, but none seem to be in support of this.
You don't have to provide a live URL as a type parameter to JsonProvider; you can also provide the filename of a sample file that reflects the structure you expect to see. With that feature, you can do the following steps:
First, log in to the service and save a JSON file that reflects the API you're going to use.
Next, do something like the following:
type TfsData = JsonProvider<"/path/to/sample/file.json">
let url = "https://example.com/login/etc"
// Use standard .Net API to log in with your Windows credentials
// Save the results in a variable `jsonResults`
let parsedResults = TfsData.Parse(jsonResults)
printfn "%A" parsedResults.Foo // At this point, Intellisense should work
This is all very generic, of course, since I don't know precisely what you need to do to log in to your service; presumably you already know how to do that. The key is to retrieve the JSON yourself, then use the .Parse() method of your provided type to parse it.

StackExchange API: Could not parse client_id

I'm trying to connect to the StackExchange API in R.
When I try:
library(httr)
end <- oauth_endpoint(authorize = "https://stackoverflow.com/oauth",
access = "https://stackoverflow.com/oauth")
myapp <- oauth_app("myapp",
key = "KEY", # tried swapping these
secret = "CLIENT SECRET",
redirect_uri = "https://stackoverflow.com/oauth/login_success")
token <- oauth2.0_token(end,
myapp)
The browser opens but leads to the following message (in the browser):
Couldn't parse `client_id`
This also happens if I try it with opposite (reversed) values of key and secret, or event with key set to either value and secret=NULL (just to test without privileged access).
The StackExchange API docs say that the key value they give you is not really a secret but the client_secret value is. In the oauth_app help it says that the secret "is not equivalent to a password, and is not really a secret". Interesting.
For now I'm just trying to establish an initial test connection.
Update:
I was curious if it was actually a matter of not being able to parse special character. I tried escaping the 2 parentheses ((() in my key and client_secret. That didn't change anything. I then tried setting both to an empty string (i.e. key = "", etc) and yet that somehow led to the same result. I feel it's a clue but I still don't know what's wrong.
You're using implicit ("Client side") OAuth(SE API Doc).
That means that the auth sequence should look like this example:
Your app HTTP GETS:
https://stackexchange.com/oauth/dialog?client_id=4709&scope=private_info&redirect_uri=https://stackexchange.com/oauth/login_success
Where client_idand scope are set to your circumstances.
Your app is then redirected to:
https://stackexchange.com/oauth/login_success#access_token=wdR8Lm7m4ibD48lfrCcFxQ))&expires=86399
For example.
Where access_token is what you need for subsequent calls that require authentication.
I'm no r coder, but guess that the syntax should be something like:
myapp <- oauth_app("myapp",
client_id = "{Your App's ID}",
scope = "private_info", # Or whatever is desired. See the doc page linked above
redirect_uri = "https://stackoverflow.com/oauth/login_success")
client_secret is only used for server-side (explicit) OAuth.
pass key in all subsequent calls, OAuth needed or not, for quota purposes.
I was getting the same error, my issue was that I was using the client secret as a value for my client_id parameter

Key not valid for use in specified state error when using ProtectedData.Unprotect

I have a little problem in using a simple ProtectedData.Unprotect call, here's the code I'm sharing, maybe I'm missing something here.
public static byte[] SampleDecrypt(IEncrypted symmetricallyEncrypted, string base64DpapiLocalEncyrptedKey)
{
if (base64DpapiLocalEncryptedKey == null)
{
throw new ArgumentNullException("base64DpapiLocalEncryptedKey");
}
byte[] unprotectedKey =
ProtectedData.Unprotect(
base64DpapiLocalEncyrptedKey,
null,
DataProtectionScope.LocalMachine);
return unprotectedKey;
}
Where base64DpapiLocalEncyrptedKey is:
"ABCCENCMnd8CFdERjHoAVV/Pl+sMAAAA4q4wemrun5a67ohPku3cIAQCCCBAAAAKKKDZgAAqAAAABADDDCvGV5W6fCNcWbb9LPZp2U3AAAYYYSBBBCgDDDDEAAAANlpDcUbBvGqMyHXk8CPtUEoBBBBlB1TtMZRC05ASxGV1/c3U548eVSPUO4X307ZDjRYytjNC35Di92q9RQAAACN//xNkexvIrGULI9GG9MdyS9Lee=="
when I ran the above it gives me the "Key not valid for use in specified state"
Thank you so much in advance guys!
I've figured out the problem. DPAPI pairs the encrypted key with your machine (assuming it's encrypted using a machine scope) in my case, localmachine scope was used.
Thought it may help anyone out there having the same issues. Try the key onto different machines to see if one works and not on the other to verify that you have a wrong key.
I created a new key off of a different server and was able to use it.

A way to generate a signature or a hash of an image in ASP.NET for duplicate detection?

I run a rather large site where my members add thousands of images every day. Obviously there is a lot of duplication and i was just wondering if during an upload of an image i can somehow generate a signature or a hash of an image so i can store it. And every time someone uploads the picture i would simply run a check if this signature already exists and fire an error stating that this image already exists. Not sure if this kind of technology already exists for asp.net but i am aware of tineye.com which sort of does it already.
If you think you can help i would appreciate your input.
Kris
A keyword that might be of interest is perceptual hashing.
You use any derived HashAlgorithm to generate a hash from the byte array of the file. Usually MD5 is used, but you could subsitute this for any of those provided in the System.Security.Cryptography namespace. This works for any binary, not just images.
Lots of sites provide MD5 hashes when you download files to verify if you've downloaded the file properly. For instance, an ISO CD/DVD image may be missing bytes when you've received the whole thing. Once you've downloaded the file, you generate the hash for it and make sure it's the same as the site says it should be. If all compares, you've got an exact copy.
I would probably use something similar to this:
public static class Helpers
{
//If you're running .NET 2.0 or lower, remove the 'this' keyword from the
//method signature as 2.0 doesn't support extension methods.
static string GetHashString(this byte[] bytes, HashAlgorithm cryptoProvider)
{
byte[] hash = cryptoProvider.ComputeHash(bytes);
return Convert.ToBase64String(hash);
}
}
Requires:
using System.Security.Cryptography;
Call using:
byte[] bytes = File.ReadAllBytes("FilePath");
string filehash = bytes.GetHashString(new MD5CryptoServiceProvider());
or if you're running in .NET 2.0 or lower:
string filehash = Helpers.GetHashString(File.ReadAllBytes("FilePath"), new MD5CryptoServiceProvider());
If you were to decide to go with a different hashing method instead of MD5 for the miniscule probability of collisions:
string filehash = bytes.GetHashString(new SHA1CryptoServiceProvider());
This way your has method isn't crypto provider specific and if you were to decide you wanted to change which crypto provider you're using, you just inject a different one into the cryptoProvider parameter.
You can use any of the other hashing classes just by changing the service provider you pass in:
string md5Hash = bytes.GetHashString(new MD5CryptoServiceProvider());
string sha1Hash = bytes.GetHashString(new SHA1CryptoServiceProvider());
string sha256Hash = bytes.GetHashString(new SHA256CryptoServiceProvider());
string sha384Hash = bytes.GetHashString(new SHA384CryptoServiceProvider());
string sha512Hash = bytes.GetHashString(new SHA512CryptoServiceProvider());
Typically you'd just use MD5 or similar to create a hash. This isn't guaranteed to be unique though, so I'd recommend you use the hash as a starting point. Identify if the image matches any known hashes you stored, then individually load the ones that it does match and do a full byte comparison on the potential collisions to be sure.
Another, simpler technique though is to simply pick a smallish number of bits and read first part of the image... store that number of starting bits as if they were a hash. This still gives you a small number of potential collisions that you'd need to check, but has much less overhead.
Look in the System.Security.Cryptography namespace. You have your choice of several hashing algorithms/implementations. Here's an example using md5, but since you have a lot of these you might want something bigger like SHA1:
public byte[] HashImage(Stream imageData)
{
return new MD5CryptoServiceProvider().ComputeHash(imageData);
}
I don't know if it already exists or not, but I can't think of a reason you can't do this yourself. Something similar to this will get you a hash of the file.
var fileStream = Request.Files[0].InputStream;//the uploaded file
var hasher = System.Security.Cryptography.HMACMD5();
var theHash = hasher.ComputeHash(fileStream);
System.Security.Cryptography

Resources