Unable to sign text block with Private Key - public-key-encryption

I am trying to create a digital signature of a load of clipboard text. I am:
Creating a SHA-256 hash of the plain text.
Encrypting this hash with my PRIVATE key.
Attempting to decrypt this with my PUBLIC key.
I'm doing this as I am of the understanding that anything signed with my PRIVATE key can be decrypted with my PUBLIC - such as this for verification? Is this wrong?
I'm encrypting the hash with these methods:
public static string EncryptText(string text, int keySize, string publicKey)
{
var encrypted = Encrypt(Encoding.UTF8.GetBytes(text), keySize, publicKey);
return Convert.ToBase64String(encrypted);
}
public static byte[] Encrypt(byte[] data, int keySize, string publicKeyXml)
{
if (data == null || data.Length == 0) throw new ArgumentException("Data are empty", "data");
int maxLength = GetMaxDataLength(keySize);
if (data.Length > maxLength) throw new ArgumentException(String.Format("Maximum data length is {0}", maxLength), "data");
if (!IsKeySizeValid(keySize)) throw new ArgumentException("Key size is not valid", "keySize");
if (String.IsNullOrEmpty(publicKeyXml)) throw new ArgumentException("Key is null or empty", "publicKeyXml");
using (var provider = new RSACryptoServiceProvider(keySize))
{
provider.FromXmlString(publicKeyXml);
return provider.Encrypt(data, OptimalAsymmetricEncryptionPadding);
}
}
but passing my PRIVATE KEY down instead of my PUBLIC KEY.
Then to verify the signature, I am using:
public static string DecryptText(string privateKey, int keySize, string text)
{
var decrypted = Decrypt(Convert.FromBase64String(text), keySize, privateKey);
return Encoding.UTF8.GetString(decrypted);
}
public static byte[] Decrypt(byte[] data, int keySize, string publicAndPrivateKeyXml)
{
if (data == null || data.Length == 0) throw new ArgumentException("Data are empty", "data");
if (!IsKeySizeValid(keySize)) throw new ArgumentException("Key size is not valid", "keySize");
if (String.IsNullOrEmpty(publicAndPrivateKeyXml)) throw new ArgumentException("Key is null or empty", "publicAndPrivateKeyXml");
using (var provider = new RSACryptoServiceProvider(keySize))
{
provider.FromXmlString(publicAndPrivateKeyXml);
return provider.Decrypt(data, OptimalAsymmetricEncryptionPadding);
}
}
but passing down my PUBLIC KEY rather than the PRIVATE KEY. At this point, I am getting an error "Key does not exist".
I'm presuming this is the case because the PRIVATE KEY contains the relevant key information for the PUBLIC KEY so it can decode this one-way.
How can I sign a block of text in this way that allows me to distribute a signature with it, that can be decrypted by anybody who knows my PUBLIC KEY?

After much trawling, I found this page:
http://juzzbott.com.au/blog/signing-and-verifying-data-within-csharp

Related

JWT signing with public and private key

I have written this portion of code to create a JWT.
public String createJWT() throws JoseException {
RsaJsonWebKey rsaJsonWebKey = RsaJwkGenerator.generateJwk(2048);
// Give the JWK a Key ID (kid), which is just the polite thing to do
rsaJsonWebKey.setKeyId(keyId);
// Create the Claims, which will be the content of the JWT
JwtClaims claims = new JwtClaims();
claims.setIssuer(issuer);
claims.setExpirationTimeMinutesInTheFuture(60);
claims.setJwtId(keyId);
claims.setIssuedAtToNow();
claims.setNotBeforeMinutesInThePast(2);
claims.setSubject(subject);
// We create a JsonWebSignature object.
JsonWebSignature jws = new JsonWebSignature();
// The payload of the JWS is JSON content of the JWT Claims
jws.setPayload(claims.toJson());
//The header of the JWS
jws.setHeader("typ", "JWT");
// The JWT is signed using the private key
jws.setKey(rsaJsonWebKey.getPrivateKey());
jws.setKeyIdHeaderValue(rsaJsonWebKey.getKeyId());
// Set the signature algorithm on the JWT/JWS that will integrity protect the claims
jws.setAlgorithmHeaderValue(AlgorithmIdentifiers.RSA_USING_SHA256);
// Sign the JWS and produce the compact serialization or the complete JWT/JWS
// representation, which is a string consisting of three dot ('.') separated
// base64url-encoded parts in the form Header.Payload.Signature
String jwt = jws.getCompactSerialization();
System.out.println("JWT: " + jwt);
return jwt;
}
But I don't understand which private key is it retrieving? How can I customize this code to send my own public and private key stored in local JKS??
Thanks in advancee!!
Try to use the following to load your own keystore:
try (InputStream is = new FileInputStream(new File("path to keystore"))) {
KeyStore keyStore = KeyStore.getInstance(ksType);
keyStore.load(is, password);
final Enumeration<String> aliases = keyStore.aliases();
final String alias = aliases.nextElement(); // assuming only one entry
final Entry entry = keyStore.getEntry(alias, password);
if (entry instanceof PrivateKeyEntry) {
PrivateKeyEntry pke = (PrivateKeyEntry) entry;
PrivateKey privateKey = pke .getPrivateKey();
// and here you may return the PrivateKey
}
} catch (Exception e) {
...
}
Disclaimer : I did not test the code, but it should work.

Hive UDF - Generic UDF for all Primitive Type

I am trying to implement the Hive UDF with Parameter and so I am extending GenericUDF class.
The problem is my UDF works find on String Datatype however it throws error if I run on other data types. I want UDF to run regardless of data type.
Would someone please let me know what's wrong with following code.
#Description(name = "Encrypt", value = "Encrypt the Given Column", extended = "SELECT Encrypt('Hello World!', 'Key');")
public class Encrypt extends GenericUDF {
StringObjectInspector key;
StringObjectInspector col;
#Override
public ObjectInspector initialize(ObjectInspector[] arguments) throws UDFArgumentException {
if (arguments.length != 2) {
throw new UDFArgumentLengthException("Encrypt only takes 2 arguments: T, String");
}
ObjectInspector keyObject = arguments[1];
ObjectInspector colObject = arguments[0];
if (!(keyObject instanceof StringObjectInspector)) {
throw new UDFArgumentException("Error: Key Type is Not String");
}
this.key = (StringObjectInspector) keyObject;
this.col = (StringObjectInspector) colObject;
return PrimitiveObjectInspectorFactory.javaStringObjectInspector;
}
#Override
public Object evaluate(DeferredObject[] deferredObjects) throws HiveException {
String keyString = key.getPrimitiveJavaObject(deferredObjects[1].get());
String colString = col.getPrimitiveJavaObject(deferredObjects[0].get());
return AES.encrypt(colString, keyString);
}
#Override
public String getDisplayString(String[] strings) {
return null;
}
}
Error
java.lang.ClassCastException: org.apache.hadoop.hive.serde2.objectinspector.primitive.JavaIntObjectInspector cannot be cast to org.apache.hadoop.hive.serde2.objectinspector.primitive.StringObjectInspector
I would suggest you to replace StringObjectInspector col with PrimitiveObjectInspector col and the corresponding cast this.col = (PrimitiveObjectInspector) colObject. Then there are two ways:
First is to process every possible Primitive type, like this
switch (((PrimitiveTypeInfo) colObject.getTypeInfo()).getPrimitiveCategory()) {
case BYTE:
case SHORT:
case INT:
case LONG:
case TIMESTAMP:
cast_long_type;
case FLOAT:
case DOUBLE:
cast_double_type;
case STRING:
everyting_is_fine;
case DECIMAL:
case BOOLEAN:
throw new UDFArgumentTypeException(0, "Unsupported yet");
default:
throw new UDFArgumentTypeException(0,
"Unsupported type");
}
}
Another way, is to use PrimitiveObjectInspectorUtils.getString method:
Object colObject = col.getPrimitiveJavaObject(deferredObjects[0].get());
String colString = PrimitiveObjectInspectorUtils.getString(colObject, key);
It just pseudocode like examples. Hope it helps.

CrmServiceClient cannot be instantiated

We have a situation where the CrmServiceClient class cannot be instantiated, with an 'Object reference not set to an object' error coming from deep within the bowels of the constructor. I've also received a Collection was modified; enumeration operation may not execute error in a few situations.
This does not happen all the time, but we seem to be able to reproduce it when we trigger multiple requests very quickly.
We create the object as follows:
var ctx = new CrmServiceClient(ConfigurationManager.ConnectionStrings["Xrm"].ConnectionString);
The connection string is valid and we have set RequireNewInstance to true
We were originally using the ctx in a using block but we were advised that we shouldn't be disposing of the CrmServiceClient, so we've removed the using block, but this has not resolved the problem.
The stack trace is below - i've only pasted the relevant part. The stack leading up to this point can be any piece of code that attempts to connect to the CRM to retrieve data
at System.ThrowHelper.ThrowInvalidOperationException(ExceptionResource resource)
at System.Collections.Generic.List`1.Enumerator.MoveNextRare()
at System.Collections.Generic.List`1.Enumerator.MoveNext()
at Microsoft.Xrm.Tooling.Connector.Utilities.GetOrgnameAndOnlineRegionFromServiceUri(Uri serviceUri, String& onlineRegion, String& organizationName, Boolean& isOnPrem)
at Microsoft.Xrm.Tooling.Connector.CrmConnection.SetOrgnameAndOnlineRegion(Uri serviceUri)
at Microsoft.Xrm.Tooling.Connector.CrmConnection..ctor(String serviceUri, String userName, String password, String domain, String homeRealmUri, String authType, String requireNewInstance, String clientId, String redirectUri, String tokenCacheStorePath, String loginPrompt, String certStoreName, String certThumbprint, String skipDiscovery)
at Microsoft.Xrm.Tooling.Connector.CrmConnection..ctor(IDictionary`2 connection)
at Microsoft.Xrm.Tooling.Connector.CrmConnection.Parse(String connectionString)
at Microsoft.Xrm.Tooling.Connector.CrmServiceClient.ConnectToCrmWebService(String crmConnectionString)
at Microsoft.Xrm.Tooling.Connector.CrmServiceClient..ctor(String crmConnectionString)
I believe I've tracked down the issue. I used DotNetPeek to look at the underlying code that was failing. The static method GetOrgnameAndOnlineRegionFromServiceUriwas where the error was occurring.
I tracked it down to a static list (discoSvcs) that was being set to null before the method returns. Other threads that call this method are also trying to do things with this list. It ends up that there is a race condition where one thread could check to see if it isn't null.
The only way I can get around it now is making sure only one CrmServiceClient is being instantiated at any time, by using a lock. This isn't ideal but I am running out of time
Static list definition
namespace Microsoft.Xrm.Tooling.Connector
{
public class Utilities
{
private static CrmOnlineDiscoveryServers discoSvcs;
private static List<string> _autoRetryRetrieveEntityList;
private Utilities()
{
}
Problem Function
The static list variable is checked at the beginning of this function and if it is null, it is populated with some values. It is then used later in the method before being set to null in the finally block.
public static void GetOrgnameAndOnlineRegionFromServiceUri(
Uri serviceUri,
out string onlineRegion,
out string organizationName,
out bool isOnPrem)
{
isOnPrem = false;
onlineRegion = string.Empty;
organizationName = string.Empty;
if (serviceUri.Host.ToUpperInvariant().Contains("DYNAMICS.COM") || serviceUri.Host.ToUpperInvariant().Contains("MICROSOFTDYNAMICS.DE") || (serviceUri.Host.ToUpperInvariant().Contains("MICROSOFTDYNAMICS.US") || serviceUri.Host.ToUpperInvariant().Contains("DYNAMICS-INT.COM")))
{
if (Utilities.discoSvcs == null)
Utilities.discoSvcs = new CrmOnlineDiscoveryServers();
try
{
List<string> stringList = new List<string>((IEnumerable<string>) serviceUri.Host.Split(new string[1]
{
"."
}, StringSplitOptions.RemoveEmptyEntries));
organizationName = stringList[0];
stringList.RemoveAt(0);
StringBuilder stringBuilder = new StringBuilder();
foreach (string str in stringList)
{
if (!str.Equals("api"))
stringBuilder.AppendFormat("{0}.", (object) str);
}
string crmKey = stringBuilder.ToString().TrimEnd('.').TrimEnd('/');
stringBuilder.Clear();
if (!string.IsNullOrEmpty(crmKey))
{
CrmOnlineDiscoveryServer onlineDiscoveryServer = Utilities.discoSvcs.OSDPServers.Where<CrmOnlineDiscoveryServer>((Func<CrmOnlineDiscoveryServer, bool>) (w =>
{
if (w.DiscoveryServer != (Uri) null)
return w.DiscoveryServer.Host.Contains(crmKey);
return false;
})).FirstOrDefault<CrmOnlineDiscoveryServer>();
if (onlineDiscoveryServer != null && !string.IsNullOrEmpty(onlineDiscoveryServer.ShortName))
onlineRegion = onlineDiscoveryServer.ShortName;
}
isOnPrem = false;
}
finally
{
Utilities.discoSvcs.Dispose();
Utilities.discoSvcs = (CrmOnlineDiscoveryServers) null;
}
}
else
{
isOnPrem = true;
if (((IEnumerable<string>) serviceUri.Segments).Count<string>() < 2)
return;
organizationName = serviceUri.Segments[1].TrimEnd('/');
}
}

play framework session returns wrong value with sha256

I am having a problem with the session in play framework 1.2.4. When I add a SHA256-hash of a particular String ("testDude5") to the session and retrieve it afterwards, the values are not the same. It doesn't happen with other Strings like "testDude1". Here is the sample code to reproduce the result.
package controllers;
import java.io.UnsupportedEncodingException;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import play.mvc.Controller;
public class ExampleController extends Controller
{
public static final String test1 = "testDude1";
public static final String test2 = "testDude5";
public static void set()
{
session.put("test1", getHash(test1));
session.put("test2", getHash(test2));
}
public static void get()
{
String output = "";
output += "Test 1 compare: ";
output += session.get("test1").equals(getHash(test1)) ? "success" : "failed";
output += "\n";
output += "Test 2 compare: ";
output += session.get("test2").equals(getHash(test2)) ? "success" : "failed";
output += "\n";
renderText(output);
}
/**
* Generates the hash value for a password.
*
* #param password
* #return hash
*/
public static String getHash(String password)
{
// Create an digest object
MessageDigest md;
try
{
// Try to get sha-265
md = MessageDigest.getInstance("SHA-256");
// Encrypt the password
md.update(password.getBytes("UTF-8"));
// Get the encrypted password
byte[] digest = md.digest();
// Convert byte array to String
String str = new String(digest);
// Return encrypted password
return str;
}
catch (NoSuchAlgorithmException e)
{
e.printStackTrace();
}
catch (UnsupportedEncodingException e)
{
e.printStackTrace();
}
return null;
}
}
I am totally puzzled by this. Does anyone have an idea whats going on there. Thanks for any advice.
Cheers
The problem is in your getHash function. There is nothing wrong with play framework session.
public static String getHash(String password) {
....
// Get the encrypted password
byte[] digest = md.digest();
// Convert byte array to String
String str = new String(digest); // DON'T do this with digest!
// The behavior is unspecified.
According to Java API doc, this constructor "Constructs a new String by decoding the specified array of bytes using the platform's default charset...The behavior of this constructor when the given bytes are not valid in the default charset is unspecified". However your hash digest may contains something not valid in the default charset.
Play framework provides a nice utility function Codec.byteToHeString() to transform digest in byte[] into hex string. This might be just what you need.
// Codec resides in play.libs
String str = Codec.byteToHexString(digest);

How to disable Subject Key Identifier in SecurityTokenResolver

I am processing a SAML2 token in WIF which contains an EncryptedAssertion. The mark-up does NOT contain a "Subject Identifier Key" Extension property and as such WIF SecurityTokenHandler fails as it tries to get the correct X509 certificate from the LocalMachineStore/Personal.
The issue is clearly that the certificate used to encrypt the token does not contain the SKI Extension and of course the token generation code (Java) does not do seem to require it. To avoid having to modify the generation code is there a way I can get WIF SecuityTokenResolver to NOT check the received Token for the SKI but simply use the local store certificate directly to decrypt the token?
In the end I just implemented a custom SecurityTokenResolver and implemented the TryResolveSecurityKeyCore method.
Here is the code:
public class mySaml2SSOSecurityTokenResolver : SecurityTokenResolver
{
List<SecurityToken> _tokens;
public PortalSSOSecurityTokenResolver(List<SecurityToken> tokens)
{
_tokens = tokens;
}
protected override bool TryResolveSecurityKeyCore(System.IdentityModel.Tokens.SecurityKeyIdentifierClause keyIdentifierClause, out System.IdentityModel.Tokens.SecurityKey key)
{
var token = _tokens[0] as X509SecurityToken;
var myCert = token.Certificate;
key = null;
try
{
var ekec = keyIdentifierClause as EncryptedKeyIdentifierClause;
if (ekec != null)
{
switch (ekec.EncryptionMethod)
{
case "http://www.w3.org/2001/04/xmlenc#rsa-1_5":
{
var encKey = ekec.GetEncryptedKey();
var rsa = myCert.PrivateKey as RSACryptoServiceProvider;
var decKey = rsa.Decrypt(encKey, false);
key = new InMemorySymmetricSecurityKey(decKey);
return true;
}
}
var data = ekec.GetEncryptedKey();
var id = ekec.EncryptingKeyIdentifier;
}
}
catch (Exception ex)
{
// Do something here }
return true;
}
protected override bool TryResolveTokenCore(System.IdentityModel.Tokens.SecurityKeyIdentifierClause keyIdentifierClause, out System.IdentityModel.Tokens.SecurityToken token)
{
throw new NotImplementedException();
}
protected override bool TryResolveTokenCore(System.IdentityModel.Tokens.SecurityKeyIdentifier keyIdentifier, out System.IdentityModel.Tokens.SecurityToken token)
{
throw new NotImplementedException();
}
}
}

Resources