In my Bean Shell Sampler i am getting response as
Sun RSA public key, 2048 bits
modulus: 22295351891298217229975679072351263454572804823888397394956934480688545098388363434555311921650592166059251017638546278442305958792511628365321549674368487249258317999232492062784515102404906734978121435799114700302881045885988703962970888009290777606595760751230036638945779986258956916131307234869683993065702144540870733479633460269689089976061715241046980179651894991519601546098863574672792649655278518708922038045203420614818093220439077000089729610115783652292803355176127125944925842204444536282480600674854449097908926668384181326756503446116301460522215211454108585731728225508829847198093781511594519426983
public exponent: 65537
I just need to extract the value in the modulus field. How can we do it in Jmeter ? Help is useful!
Switch to JSR223 Sampler and Groovy language
Use the code like below to extract your "modulus" value using Regular Expression Matcher like
def response = 'Sun RSA public key, 2048 bits modulus: 22295351891298217229975679072351263454572804823888397394956934480688545098388363434555311921650592166059251017638546278442305958792511628365321549674368487249258317999232492062784515102404906734978121435799114700302881045885988703962970888009290777606595760751230036638945779986258956916131307234869683993065702144540870733479633460269689089976061715241046980179651894991519601546098863574672792649655278518708922038045203420614818093220439077000089729610115783652292803355176127125944925842204444536282480600674854449097908926668384181326756503446116301460522215211454108585731728225508829847198093781511594519426983 public exponent: 65537'
def matcher = response =~ /modulus: (.+?) public/
if (matcher.find()) {
log.info(matcher.group(1))
}
References:
Using Regular Expressions in Groovy
Apache Groovy - Why and How You Should Use It
Beanshell equivalent just in case:
import java.util.regex.Matcher;
import java.util.regex.Pattern;
String response = "Sun RSA public key, 2048 bits modulus: 22295351891298217229975679072351263454572804823888397394956934480688545098388363434555311921650592166059251017638546278442305958792511628365321549674368487249258317999232492062784515102404906734978121435799114700302881045885988703962970888009290777606595760751230036638945779986258956916131307234869683993065702144540870733479633460269689089976061715241046980179651894991519601546098863574672792649655278518708922038045203420614818093220439077000089729610115783652292803355176127125944925842204444536282480600674854449097908926668384181326756503446116301460522215211454108585731728225508829847198093781511594519426983 public exponent: 65537";
Pattern p = Pattern.compile("modulus: (.+?) public");
Matcher m = p.matcher(response);
if (m.find()){
log.info(m.group(1));
}
Related
I'm dealing with a web service that sends a public key down to the client in the following format.
DB2F71B3B998D600946FD47636122256FB9FA10A33A66707133A73CC458B9D90A593C32DD054BCF5CEA430CE512D659D689BD3E61ECCD4B18B3921FF7FB81F0433B9CE995A3DC096A8DD5C3A5F8EC6EB4C0CF1036CDBA0E29F20B54E1F690002A01F29A7BB9622B05835C23EBDF8F1A0D4581C9579B29877F1457053B681DA72A0DD4BF1133B857BEB7C3971416F12D6630F7939DF3C44DFB4555B5A8260134FC3AEB328CF76697367A336E881FE291F860E5E7BE708F9BA7C046632868B17468AC7BD8013032F17BDA9DF9DFF0552B33C8431075BA0936BDFF9E6173EF1901AFE27FD72422EAD6F77059F15BADB4F376F56C1F04D6DB52E509954399DEC28D9:10001
Note the N and e values are separated by a colon ':'.
I would like to use OpenSSL::PKey::RSA in order to work with the public key, but it only accepts DER and PEM format certs. How can I format the public key I am given into a PEM or DER format cert that is consumable by the OpenSSL wrapper library in Ruby?
EDIT:
This python code does essentially what I am attempting to do in Ruby. I'm looking for the equivalent of the RSAPublicNumbers class.
https://github.com/jpf/okta-jwks-to-pem/blob/master/jwks_to_pem.py#L40
Check base64_to_long
def generate_key_from_jwks(kid_header)
key = OpenSSL::PKey::RSA.new
exponent = kid_header['e']
modulus = kid_header['n']
key.set_key(base64_to_long(modulus), base64_to_long(exponent), nil)
end
def base64_to_long(data)
decoded_with_padding = Base64.urlsafe_decode64(data) + Base64.decode64('==')
decoded_with_padding.to_s.unpack('C*').map do |byte|
to_hex(byte)
end.join.to_i(16)
end
def to_hex(int)
int < 16 ? '0' + int.to_s(16) : int.to_s(16)
end
I am trying to create a bitcoin address in ruby according to the documentation of bitcoin wiki (bitcoin creation according bitcoin wiki).
Starting point is just some random string which emulates the output of ripmed160.
Unfortunately I don't quite succeed in doing so, here is my code:
require 'base58_gmp'
tx_hash = "a8d0c0184dde994a09ec054286f1ce581bebf46446a512166eae7628734ea0a5"
ripmed160 = tx_hash[0..39]
ripmed160_with_pre = "00" + ripmed160
sha1 = Digest::SHA256.hexdigest ripmed160_with_pre
sha2 = Digest::SHA256.hexdigest sha1
bin_address = Integer("0x" + ripmed160_with_pre + sha2[0..7])
bitcoin_address = "1" + Base58GMP.encode(bin_address, 'bitcoin') # => "1GPcbTYDBwJ42MfKkedxjmJ3nrgoaNd2Sf"
I get something that looks like a bitcoin address but it is not recognised by blockchain.info so I guess it is invalid.
Can you please help me to make that work.
When you calculate the SHA256 checksum, make sure to calculate it over the actual bytes of the previous step, not the hex encoding of those bytes:
# First convert to actual bytes.
bytes = [ripmed160_with_pre].pack('H*')
# Now calculate the first hash over the raw bytes, and
# return the raw bytes again for the next hash
# (note: digest not hexdigest).
sha1 = Digest::SHA256.digest bytes
# Second SHA256, using the raw bytes from the previous step
# but this time we can use hexdigest as the rest of the code
# assumes hex encoded strings
sha2 = Digest::SHA256.hexdigest sha1
Does anyone know of a YAML deserializer that can provide position information for the constructed objects?
I know how to deserialize a YAML file into a Java object. Simple instructions on http://yamlbeans.sourceforge.net/.
However, I want to do some algorithmic validation on the deserialized object and report error back to the user pointing to the position in the YAML that cause the error.
Example:
=========YAML file==========
name: Nathan Sweet
age: 28
address: 4011 16th Ave S
=======JAVA class======
public class Contact {
public String name;
public int age;
public String address;
}
Imagine if I want to first load the yaml into Contact class and then validate the address against some repository and error back if its invalid. Something like:
'Line 3 Column 9: The address does not match valid entry in the database'
The problem is, currently there is no way to get the position inside a deserialized object from YAML.
Anyone know a solution to this issue?
Most YAML parsers, if they keep any information about positions around they drop it while constructing the language native objects.
In ruamel.yaml ¹, I keep more information around because I want to be able to round-trip with minimal loss of original layout (e.g. keeping comments and key order in mappings).
I don't keep information on individual key-value pairs, but I do on the "upper-left" position of a mapping². Because of the kept order of the mapping items you can give some rather nice feedback. Given an input file:
- name: anthon
age: 53
adres: Rijn en Schiekade 105
- name: Nathan Sweet
age: 28
address: 4011 16th Ave S
And a program that you call with the input file as argument:
#! /usr/bin/env python2.7
# coding: utf-8
# http://stackoverflow.com/questions/30677517/yaml-deserializer-with-position-information?noredirect=1#comment49491314_30677517
import sys
import ruamel.yaml
up_arrow = '↑'
def key_error(key, value, line, col, error, e='E'):
print('E[{}:{}]: {}'.format(line, col, error))
print('{}{}: {}'.format(' '*col, key, value))
print('{}{}'.format(' '*(col), up_arrow))
print('---')
def value_error(key, value, line, col, error, e='E'):
val_col = col + len(key) + 2
print('{}[{}:{}]: {}'.format(e, line, val_col, error))
print('{}{}: {}'.format(' '*col, key, value))
print('{}{}'.format(' '*(val_col), up_arrow))
print('---')
def value_warning(key, value, line, col, error):
value_error(key, value, line, col, error, e='W')
class Contact(object):
def __init__(self, vals):
for offset, k in enumerate(vals):
self.check(k, vals[k], vals.lc.line+offset, vals.lc.col)
for k in ['name', 'address', 'age']:
if k not in vals:
print('K[{}:{}]: {}'.format(
vals.lc.line+offset, vals.lc.col, "missing key: "+k
))
print('---')
def check(self, key, value, line, col):
if key == 'name':
if value[0].lower() == value[0]:
value_error(key, value, line, col,
'value should start with uppercase')
elif key == 'age':
if value < 50:
value_warning(key, value, line, col,
'probably too young for knowing ALGOL 60')
elif key == 'address':
pass
else:
key_error(key, value, line, col,
"unexpected key")
data = ruamel.yaml.load(open(sys.argv[1]), Loader=ruamel.yaml.RoundTripLoader)
for x in data:
contact = Contact(x)
giving you E(rrors), W(arnings) and K(eys missing):
E[0:8]: value should start with uppercase
name: anthon
↑
---
E[2:2]: unexpected key
adres: Rijn en Schiekade 105
↑
---
K[2:2]: missing key: address
---
W[4:7]: probably too young for knowing ALGOL 60
age: 28
↑
---
Which you should be able to parser in a calling program in any language to give feedback. The check method of course need adjusting to your requirements. This is not as nice as being to do that in the language the rest of your application is in, but it might be better than nothing.
In my experience handling the above format is certainly simpler than extending an existing (open source) YAML parser.
¹ Disclaimer: I am the author of that package
² I want to use that kind of information at some point to preserve spurious newlines, inserted for readability
In python, you can readily write custom Dumper/Loader objects and use them to load (or dump) your yaml code. You can have these objects track the file/line info:
import yaml
from collections import OrderedDict
class YamlOrderedDict(OrderedDict):
"""
An OrderedDict that was loaded from a yaml file, and is annotated
with file/line info for reporting about errors in the source file
"""
def _annotate(self, node):
self._key_locs = {}
self._value_locs = {}
nodeiter = node.value.__iter__()
for key in self:
subnode = nodeiter.next()
self._key_locs[key] = subnode[0].start_mark.name + ':' + \
str(subnode[0].start_mark.line+1)
self._value_locs[key] = subnode[1].start_mark.name + ':' + \
str(subnode[1].start_mark.line+1)
def key_loc(self, key):
try:
return self._key_locs[key]
except AttributeError, KeyError:
return ''
def value_loc(self, key):
try:
return self._value_locs[key]
except AttributeError, KeyError:
return ''
# Use YamlOrderedDict objects for yaml maps instead of normal dict
yaml.add_representer(OrderedDict, lambda dumper, data:
dumper.represent_dict(data.iteritems()))
yaml.add_representer(YamlOrderedDict, lambda dumper, data:
dumper.represent_dict(data.iteritems()))
def _load_YamlOrderedDict(loader, node):
rv = YamlOrderedDict(loader.construct_pairs(node))
rv._annotate(node)
return rv
yaml.add_constructor(yaml.resolver.BaseResolver.DEFAULT_MAPPING_TAG, _load_YamlOrderedDict)
Now when you read a yaml file, any mapping objects will be read as a YamlOrderedDict, which allows looking up the file location of keys in the mapping object. You can also add an iterator method like:
def iter_with_lines(self):
for key, val in self.items():
yield (key, val, self.key_loc(key))
...and now you can write a loop like:
for key,value,location in obj.iter_with_lines():
# iterate through the key/value pairs in a YamlOrderedDict, with
# the source file location
I'm trying to get a ruby implementation of an encryption lib that's apparently popular in the Java world -- PBEWithMD5AndDES
Does anyone know how to use openssl or another open source gem to perform encryption/decryption that's compatible with this format?
Updated:
I used a gem chilkat to implement it but it is paid, i need an opensource solution.
I know it is super old but I had the same problem and just solved it so here it goes
to encrypt, where salt is your salt sting, passkey is your password key string and iterations is number of iterations you want to use
def encrypt_account_number
cipher = OpenSSL::Cipher::Cipher.new("DES")
cipher.encrypt
cipher.pkcs5_keyivgen passkey, salt,iterations,digest
encrypted_account_number = cipher.update(account_number)
encrypted_account_number << cipher.final
Base64.encode64(encrypted_account_number )
end
def decrypt_account_number
cipher = OpenSSL::Cipher::Cipher.new("DES")
base_64_code = Base64.decode64(account_number)
cipher.decrypt
cipher.pkcs5_keyivgen passkey, salt,iterations,digest
decrypted_account_number = cipher.update base_64_code
decrypted_account_number << cipher.final
decrypted_account_number
end
You don't need to actually implement PBEWithMD5andDES assuming ruby has a DES implementation. What you need to implement is the key derivation function ( who you get a key out of a password) and then feed that derived key to DES with the appropriate mode and padding.
Thankfully, the key derivation function is not particularly security critical in implementation, so you can do it yourself safely enough. According to the rfc, PBEwithMD5AndDES is actually the PBKDF1 ( a ker derivation function) used with DES in CBC mode .
PBKDF1 does not look that hard to implement . Looks like you can do it with a for loop and an md5 call.
Note that you may still get some odd results because of the possibility of a different padding scheme being used in Java and Ruby. I assume that the spec one is pkcs 1.5 padding, but at a quick glance, I can't confirm this
5.1 PBKDF1
PBKDF1 applies a hash function, which shall be MD2 [6], MD5 [19] or
SHA-1 [18], to derive keys. The length of the derived key is bounded
by the length of the hash function output, which is 16 octets for MD2
and MD5 and 20 octets for SHA-1. PBKDF1 is compatible with the key
derivation process in PKCS #5 v1.5.
PBKDF1 is recommended only for compatibility with existing
applications since the keys it produces may not be large enough for
some applications.
PBKDF1 (P, S, c, dkLen)
Options: Hash underlying hash function
Input: P password, an octet string
S salt, an eight-octet string
c iteration count, a positive integer
dkLen intended length in octets of derived key,
a positive integer, at most 16 for MD2 or
MD5 and 20 for SHA-1
Output: DK derived key, a dkLen-octet string
Steps:
1. If dkLen > 16 for MD2 and MD5, or dkLen > 20 for SHA-1, output
"derived key too long" and stop.
2. Apply the underlying hash function Hash for c iterations to the
concatenation of the password P and the salt S, then extract
the first dkLen octets to produce a derived key DK:
T_1 = Hash (P || S) ,
T_2 = Hash (T_1) ,
...
T_c = Hash (T_{c-1}) ,
DK = Tc<0..dkLen-1>
3. Output the derived key DK.
For what its' worth, I'm posting my python code, which actually works (I have tons of encrypted values which were done using org.jasypt.util.text.BasicTextEncryptor, I needed to decrypt them.)
import base64
import hashlib
from Crypto.Cipher import DES
"""
Note about PBEWithMD5AndDES in java crypto library:
Encrypt:
Generate a salt (random): 8 bytes
<start derived key generation>
Append salt to the password
MD5 Hash it, and hash the result, hash the result ... 1000 times
MD5 always gives us a 16 byte hash
Final result: first 8 bytes is the "key" and the next is the "initialization vector"
(there is something about the first 8 bytes needing to be of odd paraity, therefore
the least significant bit needs to be changed to 1 if required. We don't do it,
maybe the python crypto library does it for us)
<end derived key generation>
Pad the input string with 1-8 bytes (note: not 0-7, so we always have padding)
so that the result is a multiple of 8 bytes. Padding byte value is same as number of
bytes being padded, eg, \x07 if 7 bytes need to be padded.
Use the key and iv to encrypt the input string, using DES with CBC mode.
Prepend the encrypted value with the salt (needed for decrypting since it is random)
Base64 encode it -> this is your result
Decrypt:
Base64 decode the input message
Extract the salt (first 8 bytes). The rest is the encoded text.
Use derived key generation as in Encrypt above to get the key and iv
Decrypt the encoded text using key and iv
Remove padding -> this is your result
(I only have implemented decrypt here since that's all I needed,
but encrypt should be straighforward as well)
"""
def get_derived_key(password, salt, count):
key = password + salt
for i in range(count):
m = hashlib.md5(key)
key = m.digest()
return (key[:8], key[8:])
def decrypt(msg, password):
msg_bytes = base64.b64decode(msg)
salt = msg_bytes[:8]
enc_text = msg_bytes[8:]
(dk, iv) = get_derived_key(password, salt, 1000)
crypter = DES.new(dk, DES.MODE_CBC, iv)
text = crypter.decrypt(enc_text)
# remove the padding at the end, if any
return re.sub(r'[\x01-\x08]','',text)
I've updated python script from user3392439, with encrypt support. Wish it helpful.
import base64
import hashlib
import re
import os
from Crypto.Cipher import DES
"""
Note about PBEWithMD5AndDES in java crypto library:
Encrypt:
Generate a salt (random): 8 bytes
<start derived key generation>
Append salt to the password
MD5 Hash it, and hash the result, hash the result ... 1000 times
MD5 always gives us a 16 byte hash
Final result: first 8 bytes is the "key" and the next is the "initialization vector"
(there is something about the first 8 bytes needing to be of odd paraity, therefore
the least significant bit needs to be changed to 1 if required. We don't do it,
maybe the python crypto library does it for us)
<end derived key generation>
Pad the input string with 1-8 bytes (note: not 0-7, so we always have padding)
so that the result is a multiple of 8 bytes. Padding byte value is same as number of
bytes being padded, eg, \x07 if 7 bytes need to be padded.
Use the key and iv to encrypt the input string, using DES with CBC mode.
Prepend the encrypted value with the salt (needed for decrypting since it is random)
Base64 encode it -> this is your result
Decrypt:
Base64 decode the input message
Extract the salt (first 8 bytes). The rest is the encoded text.
Use derived key generation as in Encrypt above to get the key and iv
Decrypt the encoded text using key and iv
Remove padding -> this is your result
(I only have implemented decrypt here since that's all I needed,
but encrypt should be straighforward as well)
"""
def get_derived_key(password, salt, count):
key = password + salt
for i in range(count):
m = hashlib.md5(key)
key = m.digest()
return (key[:8], key[8:])
def decrypt(msg, password):
msg_bytes = base64.b64decode(msg)
salt = msg_bytes[:8]
enc_text = msg_bytes[8:]
(dk, iv) = get_derived_key(password, salt, 1000)
crypter = DES.new(dk, DES.MODE_CBC, iv)
text = crypter.decrypt(enc_text)
# remove the padding at the end, if any
return re.sub(r'[\x01-\x08]','',text)
def encrypt(msg, password):
salt = os.urandom(8)
pad_num = 8 - (len(msg) % 8)
for i in range(pad_num):
msg += chr(pad_num)
(dk, iv) = get_derived_key(password, salt, 1000)
crypter = DES.new(dk, DES.MODE_CBC, iv)
enc_text = crypter.encrypt(msg)
return base64.b64encode(salt + enc_text)
def main():
msg = "hello, world"
passwd = "mypassword"
s = encrypt(msg, passwd)
print s
print decrypt(s, passwd)
if __name__ == "__main__":
main()
For #cooljohny
I do not really recall how this code works, but I'm 99% sure it does. I wrote it by carefully digging through the spec from the Java implementation of pbewithmd5anddes, and testing this python against that. I delivered exactly this code to a client, and it worked fine for them. I changed the constants before pasting it here, but that's all. You should be able to confirm that it produces the same encrypted output as the Java lib, and then replicate it in ruby. Good luck!
import base64
from Crypto.Cipher import DES
from passlib.utils.pbkdf2 import pbkdf1
password = 'xxxxxxx'
iterations = 22
salt_bytes = [19,15,78,45,34,90,12,11]
# convert saltBytes to a string
salt_string = ''.join([chr(a) for a in salt_bytes])
# a sample request
raw_data = '''{"something":"to","encrypt":"here"}'''
# from the standard...
padding_value = (8 - (raw_data.__len__() % 8))
padding_data = chr(padding_value) * padding_value
padded_data = raw_data + padding_data
# 22 iterations, 16 is the # of bytes in an md5 digest
pbkres = pbkdf1(password, salt_string, iterations, 16, 'md5')
# split the digest into two 8-byte halves
# this gives the DES secret key and initializing vector
des_key, iv = pbkres[0:8], pbkres[8:16]
# encrypt with DES
cipher = DES.new(des_key, DES.MODE_CBC, iv)
cmsg = cipher.encrypt(padded_data)
# and base64 encode
base64.b64encode(cmsg)
What is the definition of an s2k algorithm? For example, "PBKDF2(SHA-1)" is an s2k algorithm.
Here is some Botan code that refers to s2k:
AutoSeeded_RNG rng;
std::auto_ptr<S2K> s2k(get_s2k("PBKDF2(SHA-1)"));
s2k->set_iterations(8192);
s2k->new_random_salt(rng, 8);
SymmetricKey bc_key = s2k->derive_key(key_len, "BLK" + passphrase);
InitializationVector iv = s2k->derive_key(iv_len, "IVL" + passphrase);
SymmetricKey mac_key = s2k->derive_key(16, "MAC" + passphrase);
String-to-key (S2K) specifiers are used to convert passphrase strings
into symmetric-key encryption/decryption keys. They are used in two
places, currently: to encrypt the secret part of private keys in the
private keyring, and to convert passphrases to encryption keys for
symmetrically encrypted messages.
Source (with more details): http://sunsite.icm.edu.pl/gnupg/rfc2440-3.html