Powershell: How to grab base64 value from attribute of SearchResultEntry object? - powershell

My goal is to fetch the published CRL of a CA from an LDAP connection.
I have a function to search the LDAP (not Active Directory!), which returns a System.DirectoryServices.Protocols.SearchResultEntryCollection as expected.
$results = LDAPsearch "$_LDAP_server`:$_LDAP_searchPort" "cn=$CA,$_LDAP_searchBase" '(&(certificateRevocationList=*))'
ForEach ($element in $results){
$element.Attributes['cn'].GetValues('string')
$element.Attributes['certificateRevocationList;binary'].GetValues('string')
}
The above properly reads the cn attribute value of each element returned, however the certificateRevocationList is returned in a strange format which does not correspond at all to the Base64 string I expect (e.g. the one that can be read if you export your data to an LDIF file or if you use the Linux ldapsearch command)...
How can I get the actual Base64 value ?
Unfortunately, you can only pass 'byte[]' or 'string' as parameter to the GetValues method (a 'Base64String' option here would be useful to me, but well...).
Current output below (where cn value is correctly written but not certificateRevocationList):

Retrieve the raw CRL as byte[], then convert to base64 yourself:
$crlBin = $element.Attributes['certificateRevocationList;binary'].GetValues('byte[]')
$crlB64 = [Convert]::ToBase64String($crlBin)

Just adding the option I ended up using, much easier since my end-goal was actually to save the CRL as a file (and be able to parse it):
$crlBin = $element.Attributes['certificateRevocationList;binary'].GetValues('byte[]')[0]
[IO.File]::WriteAllBytes("$_localDir\CRL_$CA.crl",$crlBin)
This writes the actual CRL file in DER format (can then easily be switched to PEM using certutil or openssl if needed). My initial idea was to construct a PEM-formatted CRL file from the Base64 value extracted, but I was looking way too far...
I'm leaving Mathias's response as the answer since he actually best answered my question ; I didn't specify that I wanted a CRL file in the end.

Related

Parsing a DN from certificate in pem format (correct order)

I have seen a few posts related to parsing DN from a certificate in PEM format. I am writing a UNIX script that will read the pem files in a given path and spits out their corresponding Distinguished Name (DN) in the correct order. Created a simple script but the command that parses the pem file within the script is..
openssl x509 -in <file name.pem> -noout -subject
My confusion is when I run the above command, it spits the DN in this order starting with /C=US/ST=...but I know for a fact that the certificate DN starts with "CN=" which is exact reverse of what the command is spitting out. I am having a hard time trusting which command to run that gives me the exact order because I use that order to authenticate the user and if I onboard with the wrong order, requests will not be authorized and it defeats the purpose.
The order of the component of the DN is a matter of convention. The physical order inside the binary DER encoding is the one OpenSSL shows you here. OTOH the reverted order you expected is the one that a majority of tools use and that was normalized in RFC 2253.
This "/C=US/ST=..." format is the old OpenSSL one and now obsolete. If that's the one you get by default with OpenSSL, then you're using a very old version and should probably replace it with a more recent one.
In order to control how OpenSSL will display the subject, you need to use the -nameopt option. The value you can use are :
-nameopt rfc2253 : the order you wish, and the name will be "CN=xxx,OU=xxx,ST=xxx,C=FR" (no space, reverse order).
-nameopt oneline : the name will be "C = FR, ST = xxx , OU = xxx , CN = xxx".
-nameopt compat : the name will be "/C=US/ST=xxx/OU=xxx/CN=xxx" (without the space).
One more thing, if you compare the string of the DN to authenticate a client, the only way to get a reasonably reliable result is to use the exact same tool to generate it initially and when you verify it. As soon as a DN contains a less usual element, there's too many variations between tools to get the same string representation of the DN when not using the same one and the same version.

Sed command inside TCL script

Help me understand the syntax sed.I removed single quotes, but the code still does not work.
set id [open file.txt]
# send the request, get a lot of data
set tok [::http::geturl "http://example.com"-channel $id]
# cut out the necessary data between two words
exec sed s/{"data1":\(.*\)/data2\1/ $id
close $id
set ir [open file.txt]
set phone [read $ir]
close $ir
puts $phone
The problem is that I get data from a query of the following kind
{"id":3876,"form":"index","time":21,"data":"2529423","service":"Atere","response":"WAIT"}
The brace is an element of the syntax of the language, and I need to cut exactly the value between the word and the brace. How to implement this in a script.
Your code is rather confused, as (a) you are passing a file handle to the sed command. That's not going to work. (b) you are passing an input channel to http rather than an output channel (try opening the file for writing).
About the underlying problem.
If you are receiving basic JSON data back as shown.
a) You can use a JSON parser: tcllib's json module
b) Convert it to a form that Tcl can parse as a dictionary
# Assuming the JSON data is in the $data variable, and there's no
# other data present. This also assumes the data is very basic
# there are no embedded commas. Many assumptions means this
# code is likely to break in the future. A JSON parser would
# be a better choice.
set data "\{"
append data {"id":3876,"form":"index","time":21,"data":"2529423","service":"Atere","response":"WAIT"}
append data "\}"
regsub -all {[{}:",]} $data { } data
set mydatadict $data
puts [dict get $mydatadict id]
Edit:
For http processing:
set tok [::http::geturl "http://example.com"]
set data [::http::data $tok]
::http::cleanup $tok

Powershell Byte Array input string invalid format

I've written a powershell script which changes the password of a local administrator that works well - It sets the password through a config file which contains the encrypted password and the aes key with which it was generated.
Its done the way described here: http://www.adminarsenal.com/admin-arsenal-blog/secure-password-with-powershell-encrypting-credentials-part-2
Now we have a management suite which streamlines administration of windoze and linux, and somehow it doesnt pass the aes key right into the script.
If I try to execute it through the management suite, I get the following error:
Cannot convert value "1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33" to type "System.Byte". Error: "Input string was not in a correct Format."
I think the problem is the difference between PS and the management suite to handle variables (Or the black magic Powershell does under the hood which the management suite doesnt). In the script im reading in the aes-key from config file to a variable, which contains the values that are in the error message, which represent the aes key.
Now my question is: How do i get powershell to recognize the aes key as a byte array?
I cannot simply do a get-content C:\aes_keyfile, which maybe does the right typecast or whatever, because the streamline process has its own methods, so what I get in the script is the following:
$blah = $blahobject.get_variable("aeskey")
$blah
1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33
I cant do:
[byte[]]$new_blah = $blah - Error: Cannot convert value "1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33" to type "System.Byte[]". Error: "Input string was not in a correct format.""
What is the correct format? How can I find out what it is current and what it expects?
Ok, i found it out, thanks to your hint with the type:
I had to split it at the comma, so the right way is:
[byte[]]$new_blah = $blah.split(",")
Now the decryption of the password works.
Thanks a lot :>

Concat string and byte in http header

I'm trying to upload a zip by post request. To do this I need to send string and byte data.
Ok the problem is the binary encoding still. The original zip encoding first line is PK........,Q?E?;, where as the uploaded copy is PK........,Q.E.; The original has ? whereas the copy converts them to ..
Convert it to a string:
[System.Text.Encoding]::ASCII.GetString([byte]$file)
More readable:
$byteArray = [byte]$file
$enc = [System.Text.Encoding]::ASCII
$stringContents = $enc.GetString($byteArray)
You can use other encodings if the content of the file is actually in Unicode or some other encoding.
To see the other encodings:
[System.Text.Encoding] | Get-Member -Type Properties -Static
Edit based on comment:
I misunderstood your question. You are concerned that the bytes are being converted to the ASCII representation of the byte's numerical value.
This is not actually what is happening. When you use Write-Host, it is then that the conversion is happening, for display purposes only.
The values in the byte array are the raw binary data.
Edit based on your edit:
You are embedding the byte array $bytes in another string. This is implicitly converting it to a display-able format, which is not what you want.
$bytes does contain the raw data. In this case, what you want is for each byte to be placed directly in the string as is. You should try using the first solution I posted, and then embed $stringContents instead of $bytes in $parameters. I think this will do what you are hoping for.
Don't confuse what's printed on the screen when you display a string with what it actually contains. Although a [String] object can be more complex, at its simplest a string is an array of bytes. In C for example, you don't declare strings, you declare an array of char (which is usually a byte).
I urge you to try the method whereby you convert it to a string and comment if it's not working.

The torrent info_hash parameter

How does one calculate the info_hash parameter? Aka the hash corresponding to the info dictionar??
From official specs:
info_hash
The 20 byte sha1 hash of the bencoded form of the info value from the metainfo file. Note that this is a substring of the metainfo file.
This value will almost certainly have to be escaped.
Does this mean simply get the substring from the meta-info file and do a sha-1 hash on the reprezentative bytes??
.... because this is how i tried 12 times but without succes meaning I have compared the resulting hash with the one i should end up with..and they differ ..that + tracker response is FAILURE, unknown torrent ...or something
So how do you calculate the info_hash?
The metafile is already bencoded so I don't understand why you encode it again?
I finally got this working in Java code, here is my code:
byte metaData[]; //the raw .torrent file
int infoIdx = ?; //index of 'd' right after the "4:info" string
info_hash = SHAsum(Arrays.copyOfRange(metaData, infoIdx, metaData.length-1));
This assumes the 'info' block is the last block in the torrent file (wrong?)
Don't sort or anything like that, just use a substring of the raw torrent file.
Works for me.
bdecode the metafile. Then it's simply sha1(bencode(metadata['info']))
(i.e. bencode only the info dict again, then hash that).