Is it possible to convert NetMTLMv2 hash to NTLM hash? - hash

Is there any way to convert NetNTLMv2 to ntlm hashes?
For instance ntlm value of the 123 is
3DBDE697D71690A769204BEB12283678
Same password for user "try" in computer "PC" which has private ip address 192.168.73.130 NetNTLMv2 value is
try::PC:d158262017948de9:91642a8388d64d40f6c31b694e79363e:010100000000000058b2da67cbe0d001c575cfa48d38bec50000000002001600450047004900540049004d002d00500043003100340001001600450047004900540049004d002d00500043003100340004001600650067006900740069006d002d00500043003100340003001600650067006900740069006d002d0050004300310034000700080058b2da67cbe0d0010600040002000000080030003000000000000000000000000030000065d85a4000a167cdbbf6eff657941f52bc9ee2745e11f10c61bb24db541165800a001000000000000000000000000000000000000900240063006900660073002f003100390032002e003100360038002e0031002e00310030003700000000000000000000000000
Can we convert this NetNTLMv2 to NTLM (3DBDE697D71690A769204BEB12283678) without knowing any credentials?

There is no answer :) But it is ok, because I did a little research and found the answer. For now, there is no way to convert NetNTLMv2 to NTLM. Actually NTLM hash is the first key to generate NetNTLMv2. I decided to explain how it works.
To calculate and compare NTLMv2 you should first calculate the NTLM value of the password which is 123 in this case. To demonstrate it, I'll use python 2.7. Before starting you should import those modules hashlib, binascii, hmac .
NTLM value of 123 calculated with python like this:
_ntlm = hashlib.new("md4", "123".encode("utf-16-le")).digest()
ntlm = binascii.hexlify(_ntlm)
The result is 3dbde697d71690a769204beb12283678 and this value will be used as key for the first HMAC_MD5 calculation.
To do that we should concatenate the user name and domain name. If you don't work on the domain, you'll use your computer name. In this case, my username is try and my computer name is PC.
When we concatenate it, it'll become tryPC. Then this value is converted into unicode uppercase in little-endian format. We'll generate HMAC_MD5 hash of this value with using NTLM of 123 as a key.
"tryPC"==> "TRYPC" ==> '54005200590050004300' (UTF-16-le in hexadecimal)
We calculate this in Python like:
"tryPC".upper().encode("utf-16-le").encode("hex")
Then we calculate HMAC_MD5(54005200590050004300) with key 3dbde697d71690a769204beb12283678
In python it is calculated like this:
firstHMAC = hmac.new("3dbde697d71690a769204beb12283678".decode("hex"),"54005200590050004300".decode("hex"),hashlib.md5).hexdigest()
firstHMAC ==> 2381ca3f5e9c4534722cd511f6a4c983
After that we'll use firstHMAC as a key to calculate the HMAC_MD5 value of the Type2 challenge.
Type2 challenge is combined with server challenge and blob.
Network response for NetNTLMv2 is like this:
try::PC:d158262017948de9:91642a8388d64d40f6c31b694e79363e:010100000000000058b2da67cbe0d001c575cfa48d38bec50000000002001600450047004900540049004d002d00500043003100340001001600450047004900540049004d002d00500043003100340004001600650067006900740069006d002d00500043003100340003001600650067006900740069006d002d0050004300310034000700080058b2da67cbe0d0010600040002000000080030003000000000000000000000000030000065d85a4000a167cdbbf6eff657941f52bc9ee2745e11f10c61bb24db541165800a001000000000000000000000000000000000000900240063006900660073002f003100390032002e003100360038002e0031002e00310030003700000000000000000000000000
When we split this response according to : index 3 is the server challenge which is d158262017948de9
Index 5 which starts like "01010000..." indicates the blob value. Blob value also consists of blob signature, reserved fields, timestamp, random client nonce and target information. I don't give detail about the blob.
To calculate NTLMv2 we should concatenate the server challenge and the blob to calculate the HMAC_MD5 value of this by using firstHMAC as a key.
In Python we do that like this:
firstHMAC = "2381ca3f5e9c4534722cd511f6a4c983"
type2Challange = "d158262017948de9010100000000000058b2da67cbe0d001c575cfa48d38bec50000000002001600450047004900540049004d002d00500043003100340001001600450047004900540049004d002d00500043003100340004001600650067006900740069006d002d00500043003100340003001600650067006900740069006d002d0050004300310034000700080058b2da67cbe0d0010600040002000000080030003000000000000000000000000030000065d85a4000a167cdbbf6eff657941f52bc9ee2745e11f10c61bb24db541165800a001000000000000000000000000000000000000900240063006900660073002f003100390032002e003100360038002e0031002e00310030003700000000000000000000000000"
ntlmv2 = hmac.new(firstHMAC.decode("hex"),type2Challange.decode("hex"),hashlib.md5).hexdigest()
ntlmv2 ==> 91642a8388d64d40f6c31b694e79363e
If this value is equal to the 4th index of the NetNTLMv2 response, you'll be verified. In this case, the 4th index is equal to 91642a8388d64d40f6c31b694e79363e and that means you have the correct password.
According to server challenge and blob value, you'll always get the different NTLMv2 value and you only can calculate this if you have the correct password.
In other words, we can produce NetNTLMv2 with NTLM. However, we cannot convert back NetNTLMv2 to NTLM because [cryptographic] hash functions are one-way functions.

Related

Azure KeyVault signature fails during verification using javascript libraries intermittently

I am using Azure key vault for creating and storing my Secp256k1 keys. I am also using the sign API for getting my input string signed. I am working on a Secp256K1 blockchain network.These are steps I follow to get the signature in Golang.
Converting my Hex string into Byte[]
Sha256 of this Byte[]
RawURL encoding of this Sha.
b64.RawURLEncoding.EncodeToString(sha)
Sending this to Key vault for signature.
Decoding the response using RawURLEncoding.
b64.RawURLEncoding.DecodeString(*keyOpsResp.Result)
Doing Hex of the []Byte array returned from 5th Step.
Sending the signature to the blockchain.
The problem I am facing is that signature is invalid sometimes. As in 2/5 times it works and other times signature verification fails.
I am thinking there is some special chars or padding thing that I am missing.
How can I resolve this?
PS: Azure uses non-deterministic signatures where as chains usually use deterministic signs. I did some reading and found out that for verification it does not matter both could be verified successfully. Let me know if I am wrong.
• Since you are using base64 encode RawURL for encoding purposes, you can check whether the following parts are included in the token request for the keyvault signature validation. They are as follows: -
aud (audience): The resource of the token. Notice that this is https://vault.azure.net. This token will NOT work for any resource that does not explicitly match this value, such as graph.
iat (issued at): The number of ticks since the start of the epoch when the token was issued.
nbf (not before): The number of ticks since the start of the epoch when this token becomes valid.
exp (expiration): The number of ticks since the start of the epoch when this token expires.
appid (application ID): The GUID for the application ID making this request.
tid (tenant ID): The GUID for the tenant ID of the principal making this request. It is important that all the values be properly identified in the token for the request to work
• Also, please check the size of the block that is dependent on the target key and the algorithm to be used for validation of signature. In that, please check the ‘decryptParameters’, ‘algorithm’ and ‘ciphertext’ parameter for the returns that are displayed after the decrypt operation during signature validation.
Please find the below links for more details: -
https://learn.microsoft.com/en-us/java/api/com.azure.security.keyvault.keys.cryptography.cryptographyasyncclient.decrypt?view=azure-java-stable

Decrypting AES GCM 256 with pgcrypto (PostgresQL)

I am trying to decrypt a message with pgcrypto that is encrypted with AES GCM 256.
Specifications of the encryption:
Encryption algorithm AES
Key [secret of listener] (64-character-long hexadecimal string in configuration)
Key length 256 bits (32 bytes)
Block mode GCM
Padding None
Initialization vector In HTTP header (X-Initialization-Vector)
Authentication tag In HTTP header (X-Authentication-Tag)
So I receive a:
body
key
iv_header
auth_tag
I tried the below
with base as (
select
'F8E2F759E528CB69375E51DB2AF9B53734E393' as body,
'000102030405060708090A0B0C0D0E0F000102030405060708090A0B0C0D0E0F' as key,
'3D575574536D450F71AC76D8' as iv_header,
'19FDD068C6F383C173D3A906F7BD1D83' as auth_tag
),
out as (
select
decrypt_iv(
convert_to(concat(decode(body,'hex'),decode(auth_tag,'hex')),'LATIN1'),
decode(key, 'hex'),
decode(iv_header, 'hex'),
'aes/pad:none'
)
from base
)
select * from out
I keep getting the error decrypt_iv error: Data not a multiple of block size while I would expect to get the encoded message {"type": "PAYMENT"}
I expect that something goes wrong in the decoding and concatenating of body and auth_tag, but can't figure out what.
Some notes on what/why I did that
I concat the auth_tag to the body as several sources describe it that way.
I use the convert_to function as it seems the only way to concatenate two bytea values
I manage to decrypt this message in other languages (i.e. Snowflake or Python)
If anyone sees what I am doing wrong or has some directions it is highly appreciated.
pgcrypto only says it supports cbc and ecb. I'm not a cryptographer, but I don't think either of those is the same thing as GCM. So I don't think you can do this with pgcrypto. I don't know why it leads to the exact error you get, but it also doesn't surprise me.
If I really needed to do this inside the database, I think I do it by writing a function using pl/python3u.

How to Parse P12 File

I'm writing a parse tool to extract each field of P12 file in C language, OpenSSL is too huge for my project.
After reading PKCS# series documents and ASN.1 documents, I understand the basic parse step.
I use OpenSSL to generate a self-signed P12 file,there're some questions during parsing:
Why Certificate is not stored in a Safebag, in my case it's stored in EncryptedData field?
What does the localKeyId attribute mean? it has an OctetString, what is the OctectString used for?
Why the contentType of encryptedContentInfo is id-data? I think it should be id-encryptedData. In my case, Certificate is stored in encryptedContentInfo field.
Thanks,
CZ
The PKCS12 standard also available as rfc7292 formally allows a very wide range and combination of options, but in practice only a few of these options are used. There are basically 3 levels:
the file has type/structure PFX consisting mostly of a PKCS7/CMS ContentInfo which theoretically can be 'data' or 'signed-data' but in practice is always the former (with the nominally optional MacData appended) and contains
'AuthenticatedSafe' which is a sequence of one or more (almost always more) ContentInfo(s) each of which (separately) may be encrypted or not and contains (after decryption if applicable)
a sequence of one of more 'bag'(s) each of which contains actual data of a certain type such as an encrypted privatekey or a certificate along with optional attributes.
In practice there is usually:
one CI (at level 2) with PKCS7/CMS type 'encrypted-data' using a very weak algorithm (RC2-40) containing one or more CertBag(s) each containing a cert plus any attributes for it, and
one or more CI(s) (each) with type 'data' containing a PKCS8ShroudedKeyBag containing an encrypted privatekey (using PKCS8 as stated) usually using a strong algorithm commonly 3DES, plus attributes.
My answer here shows the first levels of parsing to find the encryption details; further parsing requires decryption as shown (for a specific case) in my answer here.
As mentioned all bags can have attributes; in practice depending on the implementation some bags may have the 'friendlyName' attribute with a value intended for people to use, and if a matching privatekey and cert are present they both have a 'localKeyId' attribute with the same value to tie them together, as explained in my answer to a different but related Q. 'localKeyId' is not intended for people to use and you should not normally present it to people.

Perl code to generate secret key for HMAC SHA256 signing?

I'm planning to use code similar to Amazon AWS samples to authenticate signed API requests. So users will have something like:
use Digest::SHA qw(hmac_sha256_base64);
my $digest = hmac_sha256_base64 ($request, $self->{SecretKey});
and attach $digest as a parameter to their request URI. The server-side will use the same algorithm to create a digest from the client URI and compare that to the value sent by the client.
What I can't find is Perl support for generating the SecretKey of the correct length to use when generating HMAC SHA256 digest.
For my Amazon AWS account I'm being given a 40 ASCII character base64 encoded string.
How do I generate a proper secret-key for my clients?
I suggest you use a PBKDF2 algorithm. PBKDF2 = "Password-based Key Derivation Function (#2)". It is defined in PKCS #5 (RFC 2898). This is the recommended way to derive a key from a password. You will need a salt, as well. A typical iteration count is 1000.
This page says it has a perl implementation of PBKDF2. I haven't tried it.
Apparently there is also a Crypto::PBKDF2, but it is saddled with dependencies you may not want.
EDIT
I just tried Anthony Thyssen's perl program for pbkdf2 - it works great. Simple, easy.

Safe non-tamperable URL component in Perl using symmetric encryption?

OK, I'm probably just having a bad Monday, but I have the following need and I'm seeing lots of partial solutions but I'm sure I'm not the first person to need this, so I'm wondering if I'm missing the obvious.
$client has 50 to 500 bytes worth of binary data that must be inserted into the middle of a URL and roundtrip to their customer's browser. Since it's part of the URL, we're up against the 1K "theoretical" limit of a GET URL. Also, $client doesn't want their customer decoding the data, or tampering with it without detection. $client would also prefer not to store anything server-side, so this must be completely standalone. Must be Perl code, and fast, in both encoding and decoding.
I think the last step can be base64. But what are the steps for encryption and hashing that make the most sense?
I have some code in a Cat App that uses Crypt::Util to encode/decode a user's email address for an email verification link.
I set up a Crypt::Util model using Catalyst::Model::Adaptor with a secret key. Then in my Controller I have the following logic on the sending side:
my $cu = $c->model('CryptUtil');
my $token = $cu->encode_string_uri_base64( $cu->encode_string( $user->email ) );
my $url = $c->uri_for( $self->action_for('verify'), $token );
I send this link to the $user->email and when it is clicked on I use the following.
my $cu = $c->model('CryptUtil');
if ( my $id = $cu->decode_string( $cu->decode_string_uri_base64($token) ) ) {
# handle valid link
} else {
# invalid link
}
This is basically what edanite just suggested in another answer. You'll just need to make sure whatever data you use to form the token with that the final $url doesn't exceed your arbitrary limit.
Create a secret key and store it on the server. If there are multiple servers and requests aren't guaranteed to come back to the same server; you'll need to use the same key on every server. This key should be rotated periodically.
If you encrypt the data in CBC (Cipher Block Chaining) mode (See the Crypt::CBC module), the overhead of encryption is at most two blocks (one for the IV and one for padding). 128 bit (i.e. 16 byte) blocks are common, but not universal. I recommend using AES (aka Rijndael) as the block cipher.
You need to authenticate the data to ensure it hasn't been modified. Depending on the security of the application, just hashing the message and including the hash in the plaintext that you encrypt may be good enough. This depends on attackers being unable to change the hash to match the message without knowing the symmetric encryption key. If you're using 128-bit keys for the cipher, use a 256-bit hash like SHA-256 (you can use the Digest module for this). You may also want to include some other things like a timestamp in the data to prevent the request from being repeated multiple times.
I see three steps here. First, try compressing the data. With so little data bzip2 might save you maybe 5-20%. I'd throw in a guard to make sure it doesn't make the data larger. This step may not be worth while.
use Compress::Bzip2 qw(:utilities);
$data = memBzip $data;
You could also try reducing the length of any keys and values in the data manually. For example, first_name could be reduced to fname.
Second, encrypt it. Pick your favorite cipher and use Crypt::CBC. Here I use Rijndael because its good enough for the NSA. You'll want to do benchmarking to find the best balance between performance and security.
use Crypt::CBC;
my $key = "SUPER SEKRET";
my $cipher = Crypt::CBC->new($key, 'Rijndael');
my $encrypted_data = $cipher->encrypt($data);
You'll have to store the key on the server. Putting it in a protected file should be sufficient, securing that file is left as an exercise. When you say you can't store anything on the server I presume this doesn't include the key.
Finally, Base 64 encode it. I would use the modified URL-safe base 64 which uses - and _ instead of + and / saving you from having to spend space URL encoding these characters in the base 64 string. MIME::Base64::URLSafe covers that.
use MIME::Base64::URLSafe;
my $safe_data = urlsafe_b64encode($encrypted_data);
Then stick it onto the URL however you want. Reverse the process for reading it in.
You should be safe on size. Encrypting will increase the size of the data, but probably by less than 25%. Base 64 will increase the size of the data by a third (encoding as 2^6 instead of 2^8). This should leave encoding 500 bytes comfortably inside 1K.
How secure does it need to be? Could you just xor the data with a long random string then add an MD5 hash of the whole lot with another secret salt to detect tampering?
I wouldn't use that for banking data, but it'd probably be fine for most web things...
big