How does Ansible Vault detect wrong password? - ansible

What mechanism does Ansible Vault use to detect wrong vault passwords? In other word, if a user inputs wrong vault password then Ansible shows error message below. How?
Decryption failed (no vault secrets were found that could decrypt)
Is there any section in Vault Payload that Ansible uses to detect wrong passwords?

The code for ansible-vault with the relevant section can be found here: https://github.com/ansible/ansible/blob/devel/lib/ansible/parsing/vault/init.py#L736
Summarised, it uses the specified password and vault ID to decrypt the file. So it will look for the vault ID in the vault file and will then try to decrypt the password. The crytpo part will only return a byte string when the decryption was successful and the expected format (PKCS7) is returned:
So first, the content of the vault is parsed (hex format is converted to actual bytes):
b_ciphertext, b_salt, b_crypted_hmac = parse_vaulttext(b_vaulttext)
Then, the relevant keys are generated from the salt and the password:
b_password = secret.bytes
b_key1, b_key2, b_iv = cls._gen_key_initctr(b_password, b_salt)
As you note correctly, the first thing that the _decrypt_cryptography function does is to check if the HMAC is correct, using one of the keys derived from the password above:
hmac = HMAC(b_key2, hashes.SHA256(), CRYPTOGRAPHY_BACKEND)
hmac.update(b_ciphertext)
try:
hmac.verify(_unhexlify(b_crypted_hmac))
except InvalidSignature as e:
raise AnsibleVaultError('HMAC verification failed: %s' % e)
Then, the actual decryption happens:
cipher = C_Cipher(algorithms.AES(b_key1), modes.CTR(b_iv), CRYPTOGRAPHY_BACKEND)
decryptor = cipher.decryptor()
unpadder = padding.PKCS7(128).unpadder()
b_plaintext = unpadder.update(
decryptor.update(b_ciphertext) + decryptor.finalize()
) + unpadder.finalize()
The b_plaintext is then returned.
So when you use the wrong password, the crypto function will return non-PKCS7 data and this then leads to the message above.

Related

How do I decrypt files that are encrypted using des command in Ruby?

I need to decrypt files that are encrypted with this command:
des -E -u -k "some key" file.in file.out.enc
The decryption code in Ruby:
def decrypt(key)
cipher = OpenSSL::Cipher.new(‘des’).decrypt
cipher.key = key
File.open(‘file.out’, ‘wb’) do |outf|
decrypted = cipher.update(File.read(‘file.in.enc’)) + cipher.final
outf.write(decrypted)
end
end
I’m getting wrong final block length error when I run the code above. I also tried decrypting using the openssl command line tool and got a bad magic number error. Any advice?
Try switching the mode, from CBC to ECB for instance with OpenSSL::Cipher.new('DES-ECB').
If you check which ciphers your Ruby installation supports by looking at OpenSSL::Cipher.ciphers, you'll find a list of available modes too.

Invalid OpenSSH key format when importing an ec2 key form an existing one

I am using the ruby EC2 SDK, Version 2. The private key material of a key generated with EC2 is stored in a string. I am trying to generate the public key material that is necessary to import the key into EC2 using OpenSSL::PKey::RSA
After that I am trying to import the key pair.
It looks like this:
kk=OpenSSL::PKey::RSA.new my_private_key_material
pub=kk.public_key
ec2.import_key_pair({key_name: "my_key", public_key_material: pub.export})
The API is throwing this error:
*** Aws::EC2::Errors::InvalidKeyFormat Exception: Key is not in valid OpenSSH public key format
I am not sure what is wrong and how to generate the public key material correctly. I already tried to Base64 encode the public key string without success.
Edit
I tried a couple of new things.
I generated a new key using the EC2 web console from scratch and then geneerated the public one the way Raphael points out below with
openssl rsa -in mykey.pem -outform PEM -pubout -out mykey.pub
The key is not encrypted.
Whey trying to import the public key, either with the web console or by code, I get the same error.
Edit 2
I found this.
When generating the public key with a different command, it works:
ssh-keygen -y
The generated public key looks different. It starts with
ssh-rsa AAAAB3NzaC1yc2EAAAADA....
While the first generated one starts with
-----BEGIN PUBLIC KEY-----
MIIBIjANBgkqhkiG....
Now the question is how to generate the first format in ruby. I also found this post on different formats.
OK, I solved it by following this post.
It turned out the public key had to be generated in a different way
kk=OpenSSL::PKey::RSA.new my_private_key_material
key=kk.public_key
type = key.ssh_type
data = [ key.to_blob ].pack('m0')
openssh_format = "#{type} #{data}"
ec2.import_key_pair({key_name: "my_key", public_key_material: openssh_format})
The documentation suggests that key contents must be encoded in Base64 client-side, however this is not the case: The SSH key contents should be provided as-is, in the format "ssh-rsa XXXXX....".
Rory is right. In NodeJS below code worked.
let keypair = fs.readFileSync(homedir + '/.ssh/id_rsa.pub');
result = await ec2.importKeyPair({
KeyName: 'KeyPairName',
PublicKeyMaterial: keypair,
}).promise();
I m using Ruby SDK V3 and this is work for me to import key to AWS
#!/usr/bin/env ruby
require 'rubygems'
require 'aws-sdk-ec2'
key_content = File.read('/home/xxx/keys/sshkey.pub')
ec2_client = Aws::EC2::Client.new()
resp = ec2_client.import_key_pair({
dry_run: false,
key_name: "test-ruby-key",
public_key_material: key_content,
})
Hope it helpful!

Jenkins: How to get an encrypted credentials password from shell script?

I was using the secrets/master.key that was there when the password was encrypted and stored to credentials.xml. But restoring the the same set of credentials.xml and master.key is not working in a new jenkins setup. I even tried to restore secret.key but that too is not working.
I also noticed the ecrypted string in is credentials.xml is also not same for same string.
I am trying to automate the jenkins setup. Is there a way I can get the encrypted password that the jenkins produce from bash?
Jenkins and its plugins usually encrypt strings using the Secret class, which (AFAICT) stores the key under ${JENKINS_HOME}/secrets/hudson.util.Secret.
I don't know of any easy standalone solution, but you can use the Jenkins Script Console (or the groovy CLI command) to attempt to decrypt secret values that you have:
import hudson.util.Secret
Secret a = Secret.fromString('my secret value')
String ciphertext = a.getEncryptedValue()
println ciphertext
// '{AQAAABAAAAAQdIQUuG2AhKoV7mCIcd3PXBdw8ItgchIrvQrQ=}'
// or similar; will change with each new secret object
Secret b = Secret.decrypt(ciphertext)
String plaintext = b.getPlainText()
println plaintext
// 'my secret value'
host=http://$JENKINS_USERNAME:$JENKINS_PASSWORD#localhost:8080
CRUMB=$(curl -s "$host"'/crumbIssuer/api/xml?xpath=concat(//crumbRequestField,":",//crumb)')
encrypted_passphrase=$(curl -H "$CRUMB" -d "script=println(hudson.util.Secret.fromString('password').getEncryptedValue())" -X POST $host/scriptText)

Retrieve password from kerberos keytab file

I am using hadoop with kerberos keytab file name userid.keytab for a long while. But now i m not aware the password. Is it anyway to get password from the keytab file.
No, you can't.
The only thing you can get from a keytab file is the principal name:
$ ktutil
ktutil: read_kt test.wtk
ktutil: list
slot KVNO Principal
---- ---- ---------------------------------------------------------------------
1 1 hadoop_app#BLALBLABLA.LOC
Keytab contains pairs of principal and
encrypted keys (which are derived from the Kerberos password), no way to get back the password from these data.
Keytab has a principal name at the very least, but can also hold the NTLM hash of the password, next to AES hashes of the same password.
Extract hashes with https://github.com/sosdave/KeyTabExtract

`public_decrypt': padding check failed (OpenSSL::PKey::RSAError)

Im trying to decrypt using a public key.
bob = TCPSocket.open(host, port)
cs_public_key = OpenSSL::PKey::RSA.new File.read 'c_public_key.pem'
puts "Alice is connected to bob"
bobs_public_key = ""
while line = bob.gets # Read lines from socket
bobs_public_key = bobs_public_key + line # and build them
end
bobs_public_key = JSON.parse(bobs_public_key)
puts "Alice recieved Bob's Public Key:"
puts bobs_public_key["key"]
#Error is on this line.
decypted = cs_public_key.public_decrypt(Base64.decode64(bobs_public_key["digest"]))
puts decypted
and am getting the error: 'public_decrypt': padding check failed (OpenSSL::PKey::RSAError)
Can someone explain what this error means and how to avoid it?
I ran into this error recently and tracked it down the the padding algorithm used, OpenSSL::PKey::RSA is defaulting to RSA_PKCS1_PADDING, but the message was generated in another system that defaulted to using the perfered RSA_PKCS1_OAEP_PADDING. The public/private encrypt/decrypt methods all take an optional second argument to set the padding, and this fixed the issue for me.
rsa.private_decrypt encrypted_text, OpenSSL::PKey::RSA::PKCS1_OAEP_PADDING
Turns out I was encrypting the digest using the wrong private key, so that public key was unable to decrypt it and threw that error.
Please make sure that the data you are trying to decrypt with Public key should be encrypted data. From the code, it looks like you are passing plain text instead of encrypted data.
Make sure that bobs_public_key["digest"] is encrypted. Generally it is signature of the data which is encrypted and that is to be passed. Check if your data has signature.
You are getting padding error because in RSA encryption, data is treated as a big number whatever is there in binary and then its power is raised and there is some padding. For plain text or slightly modified data, that padding check may fail.
I recently faced this padding issue while trying to decrypt the key using openssl command.
openssl rsautl -decrypt -in key_raw -inkey SIT_private.pem
RSA operation error
16764:error:0407109F:rsa routines:RSA_padding_check_PKCS1_type_2:pkcs decoding error:../openssl-1.1.1k/crypto/rsa/rsa_pk1.c:251:
16764:error:04065072:rsa routines:rsa_ossl_private_decrypt:padding check failed:../openssl-1.1.1k/crypto/rsa/rsa_ossl.c:491:
In my case using -oaep option solved the problem.
openssl rsautl -decrypt -in key_raw -inkey SIT_private.pem -oaep

Resources