I'm trying to rewrite some javacode in a python script. One part of that is to deduce a simple number from a sha256 hash.
in java this function is called:
public static Long getId(byte[] publicKey) {
byte[] publicKeyHash = Crypto.sha256().digest(publicKey);
BigInteger bigInteger = new BigInteger(1, new byte[] {publicKeyHash[7], publicKeyHash[6], publicKeyHash[5],
publicKeyHash[4], publicKeyHash[3], publicKeyHash[2], publicKeyHash[1], publicKeyHash[0]});
return bigInteger.longValue();
}
The publicKey is binairy so I can't print it here, but the publicKeyHash I use for testing is: d9d5c57971eefb085e3abaf7a5a4a6cdb8185f30105583cdb09ad8f61886ec65
To my understandin the third line of this Java code converts d9d5c579 a number.
The number that belongs to the hash above is 4273301882745002507
Now I'm looking for a piece / line of python code to generate that same number from that hash.
def getId(publicKey):
publicKeyHash = binascii.hexlify(publicKey)
p = publicKeyHash
return(struct.unpack("Q",struct.pack("cccccccc",p[7],p[6],p[5],p[4],p[3],p[2],p[1],p[0]))[0])
Was a first attempt however this clearly doesn't work, it does return a number but not the correct one.
Is there anyone here familiar with both languages and able to help my translate this function?
How about (untested):
import hashlib
publicKeyHash = hashlib.sha256.digest(publicKey)
bigInt = 0
for byte in publicKeyHash[:7]:
bigInt <<= 8
bigInt |= byte
This worked:
from hashlib import sha256
import json
import struct
import binascii
def getId(publicKey):
publicKeyHash = sha256(publicKey)
p = publicKeyHash.digest()
b = bytearray(p[:8])
b.reverse()
bigInt = 0
for byte in b:
bigInt <<= 8
bigInt |= byte
#print bigInt
return(bigInt)
Related
I try to create a Google Cloud Function that automates the process of creating a windows password for my vm instance. I found this link: https://cloud.google.com/compute/docs/instances/windows/automate-pw-generation#python
Unfortunately I use Javascript regularly wherefore I need help with Java, Python or Go. In this case I decided to use python but it doesn't matter.
My settings are:
Runtime: Python 3.7
Entry point: main
Code
import base64
import copy
import datetime
import json
import time
from Crypto.Cipher import PKCS1_OAEP
from Crypto.PublicKey import RSA
from Crypto.Util.number import long_to_bytes
from oauth2client.client import GoogleCredentials
from googleapiclient.discovery import build
def GetCompute():
credentials = GoogleCredentials.get_application_default()
compute = build('compute', 'v1', credentials=credentials)
return compute
def GetInstance(compute, instance, zone, project):
cmd = compute.instances().get(instance=instance, project=project, zone=zone)
return cmd.execute()
def GetKey():
key = RSA.generate(2048)
return key
def GetModulusExponentInBase64(key):
mod = long_to_bytes(key.n)
exp = long_to_bytes(key.e)
modulus = base64.b64encode(mod)
exponent = base64.b64encode(exp)
return modulus, exponent
def GetExpirationTimeString():
utc_now = datetime.datetime.utcnow()
expire_time = utc_now + datetime.timedelta(minutes=5)
return expire_time.strftime('%Y-%m-%dT%H:%M:%SZ')
def GetJsonString(user, modulus, exponent, email):
expire = GetExpirationTimeString()
data = {'userName': user,
'modulus': modulus,
'exponent': exponent,
'email': email,
'expireOn': expire}
return json.dumps(data)
def UpdateWindowsKeys(old_metadata, metadata_entry):
new_metadata = copy.deepcopy(old_metadata)
new_metadata['items'] = [{
'key': "windows-keys",
'value': metadata_entry
}]
return new_metadata
def UpdateInstanceMetadata(compute, instance, zone, project, new_metadata):
cmd = compute.instances().setMetadata(instance=instance, project=project, zone=zone, body=new_metadata)
return cmd.execute()
def GetSerialPortFourOutput(compute, instance, zone, project):
port = 4
cmd = compute.instances().getSerialPortOutput(instance=instance, project=project, zone=zone, port=port)
output = cmd.execute()
return output['contents']
def GetEncryptedPasswordFromSerialPort(serial_port_output, modulus):
output = serial_port_output.split('\n')
for line in reversed(output):
try:
entry = json.loads(line)
if modulus == entry['modulus']:
return entry['encryptedPassword']
except ValueError:
pass
def DecryptPassword(encrypted_password, key):
decoded_password = base64.b64decode(encrypted_password)
cipher = PKCS1_OAEP.new(key)
password = cipher.decrypt(decoded_password)
return password
def main(request):
instance = 'my-instance'
zone = 'my-zone'
project = 'my-project'
user = 'my-user'
email = 'my-email'
compute = GetCompute()
key = GetKey()
modulus, exponent = GetModulusExponentInBase64(key)
instance_ref = GetInstance(compute, instance, zone, project)
old_metadata = instance_ref['metadata']
metadata_entry = GetJsonString(user, modulus, exponent, email)
new_metadata = UpdateWindowsKeys(old_metadata, metadata_entry)
result = UpdateInstanceMetadata(compute, instance, zone, project, new_metadata)
time.sleep(30)
serial_port_output = GetSerialPortFourOutput(compute, instance, zone, project)
enc_password = GetEncryptedPasswordFromSerialPort(serial_port_output, modulus)
password = DecryptPassword(enc_password, key)
print(f'Username: {user}')
print(f'Password: {password}')
ip = instance_ref['networkInterfaces'][0]['accessConfigs'][0]['natIP']
print(f'IP Address: {ip}')
As you can see I added my details to the main function and my requirements.txt looks like this:
pycrypto==2.6.1
oauth2client==4.1.3
Unfortunately it doesn't work and I receive the following error:
Object of type bytes is not JSON serializable.
I hope you can help me here. Thanks.
========
EDIT
I added ".decode()" to modulus and exponent to avoid the previous error:
def GetJsonString(user, modulus, exponent, email):
expire = GetExpirationTimeString()
data = {'userName': user,
'modulus': modulus.decode(),
'exponent': exponent.decode(),
'email': email,
'expireOn': expire}
return json.dumps(data)
But I am still not able to generate a password. I receive an error at "serial_port_output = GetSerialPortFourOutput(compute, instance, zone, project)":
error decoding modulus: illegal base64 data at input byte 1
Your function is not working because you're using Python 2.x print statement instead of python3 print() function.
Replace
print 'Username: {0}'.format(user)
with
print ('Username: {0}'.format(user))
You can also use python 3.6+ f-strings instead of format()
pring(f'Username: {user}')
I have generated the private key in swift using the following code:
let publicKeyAttr: [NSObject: NSObject] = [
kSecAttrIsPermanent:true as NSObject,
kSecAttrApplicationTag:"com.xeoscript.app.RsaFromScrach.public2".data(using: String.Encoding.utf8)! as NSObject] // added this value
let privateKeyAttr: [NSObject: NSObject] = [
kSecAttrIsPermanent:true as NSObject,
kSecAttrApplicationTag:"com.xeoscript.app.RsaFromScrach.private2".data(using: String.Encoding.utf8)! as NSObject] // added this
var keyPairAttr = [NSObject: NSObject]()
keyPairAttr[kSecAttrKeyType] = kSecAttrKeyTypeRSA
keyPairAttr[kSecAttrKeySizeInBits] = 2048 as NSObject
keyPairAttr[kSecPublicKeyAttrs] = publicKeyAttr as NSObject
keyPairAttr[kSecPrivateKeyAttrs] = privateKeyAttr as NSObject
statusCode = SecKeyGeneratePair(keyPairAttr as CFDictionary, &publicKey, &privateKey)
And then I am using the private key to sign a piece of data, using the SecKeyAlgorithm.rsaEncryptionPKCS1 algorithm.
The code to sign is as follows:
public func sign(privateKey myPrivateKey: SecKey, value: String, base64EncodingOptions: Data.Base64EncodingOptions = []) throws -> String?
{
enum LoginErrors: Error {
case badUsername
case badPassword
}
guard #available(iOS 10.0, watchOS 3.0, tvOS 10.0, *) else {
return "Not available"
}
let data = value.data(using: .utf8)!
var error: Unmanaged<CFError>?
guard let signedData = SecKeyCreateSignature(myPrivateKey,
SecKeyAlgorithm.rsaEncryptionPKCS1,
data as CFData,
&error) as Data? else
{
return nil
}
return "(signedData.base64EncodedString())"
}
I am getting this exception:
[0] (null) "NSDescription" : "algid:encrypt:RSA:PKCS1: algorithm not supported by the key <SecKeyRef algorithm id: 1, key type: RSAPrivateKey, version: 4, block size: 2048 bits, addr: 0x280a0e5a0>"
SecKeyAlgorithm.rsaEncryptionPKCS1 is incorrect, this is attempting to use the RSA private key for hybrid encryption.
Instead pass something appropriate such as rsaSignatureDigestPKCS1v15SHA256, rsaSignatureDigestPSSSHA256 or one of the other options shown here.
Note, rsaSignatureDigestPKCS1v15SHA256 is deterministic.
Additionally, I would suggest using elliptic curve signature, RSA in 2020, however tempting, is the wrong choice.
There are so many gorgeous libs that support ECC now I wouldn't be using SecKit.
Requirement:
Given a String
we need to generate Base64 encoded string using the above given string.
How can we implement it using powerBuilder.
For reference, The Java implementation of the above case is as follows:
import org.apache.tomcat.util.codec.binary.Base64;
import java.io.UnsupportedEncodingException;
public String getClientEncoded() throws UnsupportedEncodingException {
String givenString= "Input_String";
String bytesEncoded = Base64.encodeBase64String(valueToHash.getBytes("UTF-8"));
System.out.println("encoded value is " + bytesEncoded);
return bytesEncoded ;
}
============================================================
As per Matt's reply, Used this below code from the 1st link:
String ls_valueToBeEncoded
blob lblob
ls_valueToBeEncoded = "realhowto"
lblob = Blob(ls_valueToBeEncoded)
ULong lul_len, lul_buflen
Boolean lb_rtn
lul_len = Len(ablob_data)
lul_buflen = lul_len * 2
ls_encoded = Space(lul_buflen)
lb_rtn = CryptBinaryToString(ablob_data, &
lul_len, CRYPT_STRING_BASE64, &
ref ls_encoded, lul_buflen) // Used ref ls_encoded to get the string. Otherwise, junk characters gets stored in ls_encoded.`
=======================================
Used the below code in Global External Function:
`FUNCTION boolean CryptBinaryToString ( &
Blob pbBinary, &
ulong cbBinary, &
ulong dwFlags, &
Ref string pszString, &
Ref ulong pcchString ) &
LIBRARY "crypt32.dll" ALIAS FOR "CryptBinaryToStringA;Ansi"`
=========================================
According to the 1st link suggested by Matt, The string "realhowto" should be converted to "cmVhbGhvd3Rv."
But when I tried the above code, I got "cgBlAGEAbABoAG8AdwB0AG8A"
Any advise will be appreciated.
Check out this link
Make sure you look at the comments as well.
Another option is here.
Real's How To is a very good reference for many PowerBuilder tips.
My encryption examples also have the API functions used by Real's example.
http://www.topwizprogramming.com/freecode_bcrypt.html
Checked with the 1st link given by Matt.
The solution worked.
Only thing I was missing earlier was while converting the original string to blob, we need to convert via the following:
String ls_original_string
Blob lblob_test
lblob_test = Blob(ls_original_string, EncodingAnsi!)
The blob lblob_test can be passed as an argument to the function CryptBinaryToString(...)
I have a custom crypto engine for Elliptic curve, I am trying to make this compatible with Java's bouncy castle crypto, so I am testing my API (keypair generation) against Java's bouncycastle.
First thing is to share the publickey between Java & my crypto engine that way I can get the same shared secret.
My module takes Elliptic curve 32-byte X & 32-byte Y values. I was able to output X & Y from Java code by calling "publickeyJava .toString()" below and output comes formated as 'X: .... and Y: ....." (as shown below). I copy pasted these X & Y values to my custom crypto engine and verified that I was able to get the same secret as generated by Java's bouncy castle, so I know my conversion works manually.
THE PROBLEM IS HOW TO EXTRACT THESE 32-BYTE X & Y VALUES IN JAVA PROGRAMATICALLY? I used java classes to get X & Y coordinate and printed with "getW.getAffineX() and getW.AffineY()" (as shown in my code below) but the values don't seem to match the output generated from "publickey.tostring" (which is what my module needs).
Is there a way to extract X & Y values from print "pubclickey.tostring"? Please suggest.
/*** Java code that prints Elliptic curve X & Y from bouncycastle crypto ****/
public static int generateECKeys() {
try {
ECNamedCurveParameterSpec parameterSpec = ECNamedCurveTable.getParameterSpec("secp256r1");
KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("ECDH", "SC");
keyPairGenerator.initialize(parameterSpec);
KeyPair keyPair = keyPairGenerator.generateKeyPair();
PublicKey publickeyJava = keyPair.getPublic();
Log.e(TAG_LOG, "X & Y values are ...." + publickeyJava .toString());
Log.d("LOG_TAG", "BigInteger X value is = " + ((ECPublicKey) publickeyJava).getW().getAffineX().toString());
Log.d("LOG_TAG", "BigInteger Y value is = " + ((ECPublicKey) publickeyJava).getW().getAffineY().toString());
/* .....code to generate shared secret ..... */
return 1;
} catch(Exception e){e.printStackTrace();}
return 0;
}
/******** OUTPUT ********/
X & Y values are ....EC Public Key
X: f98c87d3b6db30895b275630f30df9d796d067b06e4836f5615cad84965f4f85
Y: b8b58cb767f23e4bc4db0cc371ffb50cf12aa30407c1ba236f78a6c38948c2ee
BigInteger X value is = 324637435756455760457435640555474465574856445654455076545679
BigInteger Y value is = 954378375783465749076758439759347657056597437786534984623864
Thanks
Today I got your same problem. I solved it in this way that it seems to me easier than parsing a String.
ECPublicKey publickeyJava = (ECPublicKey)keyPair.getPublic();
ECPoint ecp = chiavePubblica.getW();
// to access X and Y you can use
ecp.getAffineX()
ecp.getAffineY()
Try toString(int radix) with radix of 16, as given below to get same X and Y values
Log.d("LOG_TAG", "BigInteger X value is = " + ((ECPublicKey) publickeyJava).getW().getAffineX().**toString(16)**); Log.d("LOG_TAG", "BigInteger Y value is = " + ((ECPublicKey) publickeyJava).getW().getAffineY().**toString(**16**)**);
I am trying to convert a 128 bit binary to a uniqueidentifier in sql that is the same as in .net and java.
I know java uses big endians, so I would like to make that the base.
I can get the correct endianess in .net, but am really struggling with it in SQL Server.
Java:
byte[] bytesOfMessage = "google.com".getBytes("UTF-8");
MessageDigest md = MessageDigest.getInstance("MD5");
byte[] md5 = md.digest(bytesOfMessage);
ByteBuffer bb = ByteBuffer.wrap(md5);
LongBuffer ig = bb.asLongBuffer();
return new UUID(ig.get(0), ig.get(1));
returns 1d5920f4-b44b-27a8-02bd-77c4f0536f5a
.Net
System.Security.Cryptography.MD5 c = System.Security.Cryptography.MD5.Create();
byte[] b = c.ComputeHash(Encoding.UTF8.GetBytes("google.com"));
int z = System.Net.IPAddress.HostToNetworkOrder(BitConverter.ToInt32(b, 0));
short y = System.Net.IPAddress.HostToNetworkOrder(BitConverter.ToInt16(b, 4));
short x = System.Net.IPAddress.HostToNetworkOrder(BitConverter.ToInt16(b, 6));
Guid g = new Guid(z, y, x, b.Skip(8).ToArray());
return g;
returns 1d5920f4-b44b-27a8-02bd-77c4f0536f5a
SQL
DECLARE #s VARCHAR(MAX) = 'google.com' --'goolge.com'
DECLARE #md5 BINARY(16) = HASHBYTES
(
'MD5',
#s
)
DECLARE #a BINARY(4) =
CONVERT
(
BINARY(4),
REVERSE
(
CONVERT
(
BINARY(4),
LEFT(#md5, 4)
)
)
)
DECLARE #b BINARY(2) =
CONVERT
(
BINARY(2),
REVERSE
(
CONVERT
(
BINARY(2),
RIGHT(#md5, 12)
)
)
)
DECLARE #c BINARY(2) =
CONVERT
(
BINARY(2),
REVERSE
(
CONVERT
(
BINARY(2),
RIGHT(#md5, 10)
)
)
)
DECLARE #d BINARY(8) =
CONVERT
(
BINARY(8),
RIGHT(#md5, 8)
)
SELECT
CONVERT
(
UNIQUEIDENTIFIER,
#a + #b + #c + #d
)
returns D86B5A7F-7A25-4895-A6D0-63BA3A706627
I am able to get all three to produce the same value when converting to an int64, but the GUID is baffling me.
Original Issue
Original Answer
If you correct the spelling of google in your SQL example (it's goolge in your post), you get the right result.
SQL Server does not support UTF-8 encoding. See Description of storing UTF-8 data in SQL Server. Use suggestion from Michael Harmon to add your .NET function to SQLServer to do the conversion. See How to encode... for instructions on how to add your .NET function to SQLServer.
Alternatively, don't specify UTF-8 in your Java and .NET code. I believe SQL Server will use same 256 bit encoding for varchar as does Java and .NET. (But not totally sure of this.)