I have this script to encrypt and decrypt text.
Why is it that when converting the decrypted text byte array to ASCII there is a space in between each character?
#Encrypt:
$unencryptedData = "passwordToEncrypt"
$pfxPassword = "P#ssw0rd1"
$certLocation = "D:\Ava\CA\Scripts\Encryption\PFXfiles\f-signed.pfx"
$cert = New-Object 'System.Security.Cryptography.X509Certificates.X509Certificate2'($certLocation, $pfxPassword, [System.Security.Cryptography.X509Certificates.X509KeyStorageFlags]::Exportable)
$publicKey = $cert.PublicKey.Key.ToXmlString($false)
$privateKey = $cert.PrivateKey.ToXmlString($true)
$unencryptedDataAsByteArray = [System.Text.Encoding]::Unicode.GetBytes($unencryptedData)
$keySize = 16384
$rsaProvider = New-Object System.Security.Cryptography.RSACryptoServiceProvider($keySize)
$rsaProvider.FromXmlString($publicKey)
$encryptedDataAsByteArray = $rsaProvider.Encrypt($unencryptedDataAsByteArray, $false)
$encryptedDataAsString = [System.Convert]::ToBase64String($encryptedDataAsByteArray)
Write-Host "Encrypted password = $encryptedDataAsString"
#Decrypt:
$rsaProvider.FromXmlString($privateKey)
$encryptedDataAsByteArray = [System.Convert]::FromBase64String($encryptedDataAsString)
$decryptedDataAsByteArray = $rsaProvider.Decrypt($encryptedDataAsByteArray, $false)
$decryptedDataAsString = [System.Text.Encoding]::ASCII.GetString($decryptedDataAsByteArray)
###### "p a s s w o r d T o E n c r y p t " ######
#$decryptedDataAsString = [System.Text.Encoding]::Unicode.GetString($decryptedDataAsByteArray)
###### "passwordToEncrypt" ######
Write-Host "Decrypted password = $decryptedDataAsString"
Consult Character Encodings in the .NET Framework. [System.Text.Encoding]::Unicode is UTF-16LE so the character A is encoded as the 16-bit value 0x0041, bytes 0x41 0x00. [System.Text.Encoding]::ASCII is an 8-bit encoding so when you decode 0x41 0x00 with ASCII you get the characters A and NUL (not space) .
You have to decode your byte array with the same encoding you encoded it in.
In the line:
$unencryptedDataAsByteArray = [System.Text.Encoding]::Unicode.GetBytes($unencryptedData)
You are setting the unencrypted byte array to a Unicode string. This means 2 bytes in the array for every character in the string. When it is later decrypted, it is still 2 bytes per character.
You need to decrypt it back in reverse order. First, decrypt it back to Unicode. Then, if you need to go to ASCII, use one of the .Net Encoding.Convert methods.
Related
How do I properly convert an IP Address gotten via OleSNMP to a useable value?
I'm trying to write a Powershell script to query devices with SNMP and then display the data. Stuff works fine for simple types, but I'm having problems with the IP Addresses (and MAC addresses, but let's stick to IP for now)
Here's what I have (simplified to the problem space):
param ($ipaddr='10.1.128.114', $community='Public')
$snmp = New-Object -ComObject oleprn.OleSNMP
$snmp.open($ipaddr, $community)
$result = $snmp.get(".1.3.6.1.2.1.4.20.1.1.10.1.128.114")
$enc = [system.Text.Encoding]::ASCII
$bytes = $enc.GetBytes($result)
write-host( "bytes:" + $bytes)
Which outputs:
bytes:10 1 63 114
When I expected
bytes:10 1 128 114
For contrast, the snmp-get outputs:
$ snmpget 10.1.128.114 -c Public -v2c -On .1.3.6.1.2.1.4.20.1.1.10.1.128.114
.1.3.6.1.2.1.4.20.1.1.10.1.128.114 = IpAddress: 10.1.128.114
And yes, I realize that in my final script I'll have to walk the table instead of using a direct "get" but I need to fix my parsing first.
As mentioned in the comments, the ASCII encoding substitutes characters outside its valid range with a question mark ?, which is ASCII character 63.
More info is available in the documentation for ASCIIEncoding.GetBytes - search for "?" and you'll find this:
ASCIIEncoding does not provide error detection. Any Unicode character greater than U+007F is encoded as the ASCII question mark ("?").
Note, 0x7F is 127, so since [char] 128 is outside this range, it's being converted to the byte equivalent of ? (which is 63) when you call GetBytes.
Your code is basically doing this this:
$result = ([char] 10) + ([char] 1) + ([char] 128) + ([char] 114)
$encoding = [System.Text.Encoding]::ASCII
$bytes = $encoding.GetBytes($result)
$bytes
# 10
# 1
# 63 (i.e. "?")
# 114
You need to use an encoder which will convert characters higher than 0x7F into the equivalent bytes - something like iso-8859-1 seems to work:
$result = ([char] 10) + ([char] 1) + ([char] 128) + ([char] 114)
$encoding = [System.Text.Encoding]::GetEncoding("iso-8859-1")
$bytes = $encoding.GetBytes($result)
$bytes
# 10
# 1
# 128
# 114
I've had the pleasure to get the assignment of posting emojis in Powershell, the only problem is they have to be on the same line, and there are three. This is, my first assignment, and we have no prior teaching in this subject so after googling and searching YouTube, my best shot was this below, however, it came with some error saying something about either too high value, or too low value.
Full error text: Exception calling "ToInt32" with "2" argument (s): "The value was either too large or too small to a UInt32. "
At C: \ Users \ EG \ Downloads \ Herningsholm \ Powershell H1 \ Hardware Information.ps1: 3 char: 5
$ UnicodeInt = [System.Convert] :: toInt32 ($ StrippedUnicode, 16)
CategoryInfo: NotSpecified: (:) [], MethodInvocationException
FullyQualifiedErrorId: OverflowException
$FullUnicode = ('U+1F60E') + ('U+1F436') + ('U+1F642')
$StrippedUnicode = $FullUnicode -replace 'U\+',''
$UnicodeInt = [System.Convert]::toInt32($StrippedUnicode,16)
[System.Char]::ConvertFromUtf32($UnicodeInt)
Try this out:
Full emoji list > here
# saves unicode for each emoji https://unicode.org/emoji/charts/full-emoji-list.html
$FullUnicode0 = 'U+1F606'
$FullUnicode1 = 'U+1F605'
$FullUnicode2 = 'U+1F605'
# removes the U+ bit
$StrippedUnicode0 = $FullUnicode0 -replace 'U\+',''
$StrippedUnicode1 = $FullUnicode1 -replace 'U\+',''
$StrippedUnicode2 = $FullUnicode2 -replace 'U\+',''
# Converts the value of the specified object to a 32-bit signed integer
$UnicodeInt0 = [System.Convert]::toInt32($StrippedUnicode0,16)
$UnicodeInt1 = [System.Convert]::toInt32($StrippedUnicode1,16)
$UnicodeInt2 = [System.Convert]::toInt32($StrippedUnicode2,16)
# Converts the specified Unicode code point into a UTF-16 encoded string so that you have an emoji
$Emoji0 = [System.Char]::ConvertFromUtf32($UnicodeInt0)
$Emoji1 = [System.Char]::ConvertFromUtf32($UnicodeInt1)
$Emoji2 = [System.Char]::ConvertFromUtf32($UnicodeInt2)
write-host "$($Emoji0), $($Emoji1), $($Emoji2)"
I have a multipart file received from a server and I need to pick out the pdf part from it. I tried with removing the first x lines and the last 2 with
$content=Get-Content $originalfile
$content[0..($content.length-3)] |$outfile
but it corrupts the binary data, so what is the way to get the binary part from the file?
MIME-Version: 1.0
Content-Type: multipart/related; boundary=MIME_Boundary;
start="<6624867311297537120--4d6a31bb.16a77205e4d.3282>";
type="text/xml"
--MIME_Boundary
Content-ID: <6624867311297537120--4d6a31bb.16a77205e4d.3282>
Content-Type: text/xml; charset=utf-8
Content-Transfer-Encoding: 8bit
<?xml version="1.0" encoding="UTF-8"?>
<soapenv:Body xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/"/>
--MIME_Boundary
Content-ID:
Content-Type: application/xml
Content-Disposition: form-data; name="metadata"
<?xml version="1.0" encoding="ISO-8859-1"?>
<metadata><contentLength>64288</contentLength><etag>7e3da21f7ed1b434def94f4b</etag><contentType>application/octet-stream</contentType><properties><property><key>Account</key><value>finance</value></property><property><key>Business Unit</key><value>EU DEBMfg</value></property><property><key>Document Type</key><value>PAYABLES</value></property><property><key>Filename</key><value>test-pdf.pdf</value></property></properties></metadata>
--MIME_Boundary
Content-ID:
Content-Type: application/octet-stream
Content-Disposition: form-data; name="content"
%PDF-1.6
%âãÏÓ
37 0 obj <</Linearized 1/L 20597/O 40/E 14115/N 1/T 19795/H [ 1005 215]>>
endobj
xref
37 34
0000000016 00000 n
0000001386 00000 n
0000001522 00000 n
0000001787 00000 n
0000002250 00000 n
.
.
.
0000062787 00000 n
0000063242 00000 n
trailer
<<
/Size 76
/Prev 116
/Root 74 0 R
/Encrypt 38 0 R
/Info 75 0 R
/ID [ <C21F21EA44C1E2ED2581435FA5A2DCCE> <3B7296EB948466CB53FB76CC134E3E76> ]
>>
startxref
63926
%%EOF
--MIME_Boundary-
You need to read the file as a series of bytes and treat it as a binary file.
Next, to parse out the PDF part of the file, you need to read it again as String, so you can perform Regular Expression on it.
The String should be in an encoding that does not alter the bytes in any way, and for that, there is the special encoding Codepage 28591 (ISO 8859-1) with which the bytes in the original file are used as-is.
To do this, I've written the following helper function:
function ConvertTo-BinaryString {
# converts the bytes of a file to a string that has a
# 1-to-1 mapping back to the file's original bytes.
# Useful for performing binary regular expressions.
Param (
[Parameter(Mandatory = $True, ValueFromPipeline = $True, Position = 0)]
[ValidateScript( { Test-Path $_ -PathType Leaf } )]
[String]$Path
)
$Stream = New-Object System.IO.FileStream -ArgumentList $Path, 'Open', 'Read'
# Note: Codepage 28591 (ISO 8859-1) returns a 1-to-1 char to byte mapping
$Encoding = [Text.Encoding]::GetEncoding(28591)
$StreamReader = New-Object System.IO.StreamReader -ArgumentList $Stream, $Encoding
$BinaryText = $StreamReader.ReadToEnd()
$StreamReader.Close()
$Stream.Close()
return $BinaryText
}
Using the above function, you should be able to get the binary part from the multipart file like this:
$inputFile = 'D:\blah.txt'
$outputFile = 'D:\blah.pdf'
# read the file as byte array
$fileBytes = [System.IO.File]::ReadAllBytes($inputFile)
# and again as string where every byte has a 1-to-1 mapping to the file's original bytes
$binString = ConvertTo-BinaryString -Path $inputFile
# create your regex, all as ASCII byte characters: '%PDF.*%%EOF[\r?\n]{0,2}'
$regex = [Regex]'(?s)(\x25\x50\x44\x46[\x00-\xFF]*\x25\x25\x45\x4F\x46[\x0D\x0A]{0,2})'
$match = $regex.Match($binString)
# use a MemoryStream object to store the result
$stream = New-Object System.IO.MemoryStream
$stream.Write($fileBytes, $match.Index, $match.Length)
# save the binary data of the match as a series of bytes
[System.IO.File]::WriteAllBytes($outputFile, $stream.ToArray())
# clean up
$stream.Dispose()
Regex details:
( Match the regular expression below and capture its match into backreference number 1
\x25 Match the ASCII or ANSI character with position 0x25 (37 decimal => %) in the character set
\x50 Match the ASCII or ANSI character with position 0x50 (80 decimal => P) in the character set
\x44 Match the ASCII or ANSI character with position 0x44 (68 decimal => D) in the character set
\x46 Match the ASCII or ANSI character with position 0x46 (70 decimal => F) in the character set
[\x00-\xFF] Match a single character in the range between ASCII character 0x00 (0 decimal) and ASCII character 0xFF (255 decimal)
* Between zero and unlimited times, as many times as possible, giving back as needed (greedy)
\x25 Match the ASCII or ANSI character with position 0x25 (37 decimal => %) in the character set
\x25 Match the ASCII or ANSI character with position 0x25 (37 decimal => %) in the character set
\x45 Match the ASCII or ANSI character with position 0x45 (69 decimal => E) in the character set
\x4F Match the ASCII or ANSI character with position 0x4F (79 decimal => O) in the character set
\x46 Match the ASCII or ANSI character with position 0x46 (70 decimal => F) in the character set
[\x0D\x0A] Match a single character present in the list below
ASCII character 0x0D (13 decimal)
ASCII character 0x0A (10 decimal)
{0,2} Between zero and 2 times, as many times as possible, giving back as needed (greedy)
)
I am trying to get my Raspberry Pi 3 to display information taken from a MS SQL database onto a 2x16 character LCD. I have a script that gets the string from the database then writes it to a .txt and another that reads the .txt and displays it on the LCD. When it displays, however, it is in Unicode instead of "plain text." Is there a way to convert this so the LCD will display it properly?
I cannot insert a picture, but it is displaying like this: (u'thewordineedhere',)
This is the script I am using to get the string and write to the .txt
import pymssql
conn = pymssql.connect(server='###.##.###.##',port='1433', user='User_Name',
password='Password', database='Database_Name')
cursor = conn.cursor()
cursor.execute('Select Distinct * From Database_Name')
results = cursor.fetchall()
my_file = open("output.txt","w")
for string in results:
print (string)
my_file.write(str(string) +"\n")
my_file.close
conn.commit()
conn.close()
This is the script that reads it and displays on the LCD.
import I2C_LCD_driver
from time import *
f = open('output.txt','r')
data = f.read()
mylcd = I2C_LCD_driver.lcd()
mylcd.lcd_display_string(data, 1)
mylcd.lcd_display_string("", 2)
If necessary I can provide the I2C_LCD_driver.py, /etc/odbc.ini, /etc/odbcinst.ini, and /etc/freetds/freetds.conf scripts as well.
Here is the I2C_LCD_driver.py
# -*- coding: utf-8 -*-
# Original code found at:
# https://gist.github.com/DenisFromHR/cc863375a6e19dce359d
"""
Compiled, mashed and generally mutilated 2014-2015 by Denis Pleic
Made available under GNU GENERAL PUBLIC LICENSE
# Modified Python I2C library for Raspberry Pi
# as found on http://www.recantha.co.uk/blog/?p=4849
# Joined existing 'i2c_lib.py' and 'lcddriver.py' into a single library
# added bits and pieces from various sources
# By DenisFromHR (Denis Pleic)
# 2015-02-10, ver 0.1
"""
# i2c bus (0 -- original Pi, 1 -- Rev 2 Pi)
I2CBUS = 1
# LCD Address
ADDRESS = 0x3F
import smbus
from time import sleep
class i2c_device:
def __init__(self, addr, port=I2CBUS):
self.addr = addr
self.bus = smbus.SMBus(port)
# Write a single command
def write_cmd(self, cmd):
self.bus.write_byte(self.addr, cmd)
sleep(0.0001)
# Write a command and argument
def write_cmd_arg(self, cmd, data):
self.bus.write_byte_data(self.addr, cmd, data)
sleep(0.0001)
# Write a block of data
def write_block_data(self, cmd, data):
self.bus.write_block_data(self.addr, cmd, data)
sleep(0.0001)
# Read a single byte
def read(self):
return self.bus.read_byte(self.addr)
# Read
def read_data(self, cmd):
return self.bus.read_byte_data(self.addr, cmd)
# Read a block of data
def read_block_data(self, cmd):
return self.bus.read_block_data(self.addr, cmd)
# Read a single byte
def read(self):
return self.bus.read_byte(self.addr)
# Read
def read_data(self, cmd):
return self.bus.read_byte_data(self.addr, cmd)
# Read a block of data
def read_block_data(self, cmd):
return self.bus.read_block_data(self.addr, cmd)
# commands
LCD_CLEARDISPLAY = 0x01
LCD_RETURNHOME = 0x02
LCD_ENTRYMODESET = 0x04
LCD_DISPLAYCONTROL = 0x08
LCD_CURSORSHIFT = 0x10
LCD_FUNCTIONSET = 0x20
LCD_SETCGRAMADDR = 0x40
LCD_SETDDRAMADDR = 0x80
# flags for display entry mode
LCD_ENTRYRIGHT = 0x00
LCD_ENTRYLEFT = 0x02
LCD_ENTRYSHIFTINCREMENT = 0x01
LCD_ENTRYSHIFTDECREMENT = 0x00
# flags for display on/off control
LCD_DISPLAYON = 0x04
LCD_DISPLAYOFF = 0x00
LCD_CURSORON = 0x02
LCD_CURSOROFF = 0x00
LCD_BLINKON = 0x01
LCD_BLINKOFF = 0x00
# flags for display/cursor shift
LCD_DISPLAYMOVE = 0x08
LCD_CURSORMOVE = 0x00
LCD_MOVERIGHT = 0x04
LCD_MOVELEFT = 0x00
# flags for function set
LCD_8BITMODE = 0x10
LCD_4BITMODE = 0x00
LCD_2LINE = 0x08
LCD_1LINE = 0x00
LCD_5x10DOTS = 0x04
LCD_5x8DOTS = 0x00
# flags for backlight control
LCD_BACKLIGHT = 0x08
LCD_NOBACKLIGHT = 0x00
En = 0b00000100 # Enable bit
Rw = 0b00000010 # Read/Write bit
Rs = 0b00000001 # Register select bit
class lcd:
#initializes objects and lcd
def __init__(self):
self.lcd_device = i2c_device(ADDRESS)
self.lcd_write(0x03)
self.lcd_write(0x03)
self.lcd_write(0x03)
self.lcd_write(0x02)
self.lcd_write(LCD_FUNCTIONSET | LCD_2LINE | LCD_5x8DOTS | LCD_4BITMODE)
self.lcd_write(LCD_DISPLAYCONTROL | LCD_DISPLAYON)
self.lcd_write(LCD_CLEARDISPLAY)
self.lcd_write(LCD_ENTRYMODESET | LCD_ENTRYLEFT)
sleep(0.2)
# clocks EN to latch command
def lcd_strobe(self, data):
self.lcd_device.write_cmd(data | En | LCD_BACKLIGHT)
sleep(.0005)
self.lcd_device.write_cmd(((data & ~En) | LCD_BACKLIGHT))
sleep(.0001)
def lcd_write_four_bits(self, data):
self.lcd_device.write_cmd(data | LCD_BACKLIGHT)
self.lcd_strobe(data)
# write a command to lcd
def lcd_write(self, cmd, mode=0):
self.lcd_write_four_bits(mode | (cmd & 0xF0))
self.lcd_write_four_bits(mode | ((cmd << 4) & 0xF0))
# write a character to lcd (or character rom) 0x09: backlight | RS=DR<
# works!
def lcd_write_char(self, charvalue, mode=1):
self.lcd_write_four_bits(mode | (charvalue & 0xF0))
self.lcd_write_four_bits(mode | ((charvalue << 4) & 0xF0))
# put string function with optional char positioning
def lcd_display_string(self, string, line=1, pos=0):
if line == 1:
pos_new = pos
elif line == 2:
pos_new = 0x40 + pos
elif line == 3:
pos_new = 0x14 + pos
elif line == 4:
pos_new = 0x54 + pos
self.lcd_write(0x80 + pos_new)
for char in string:
self.lcd_write(ord(char), Rs)
# clear lcd and set to home
def lcd_clear(self):
self.lcd_write(LCD_CLEARDISPLAY)
self.lcd_write(LCD_RETURNHOME)
# define backlight on/off (lcd.backlight(1); off= lcd.backlight(0)
def backlight(self, state): # for state, 1 = on, 0 = off
if state == 1:
self.lcd_device.write_cmd(LCD_BACKLIGHT)
elif state == 0:
self.lcd_device.write_cmd(LCD_NOBACKLIGHT)
# add custom characters (0 - 7)
def lcd_load_custom_chars(self, fontdata):
self.lcd_write(0x40);
for char in fontdata:
for line in char:
self.lcd_write_char(line)
When a row of data is read from the database, it comes back as a row object which can have the individual columns accessed as if it was a list. What you're seeing is the string representation of a row object. You want the first item so you need to use string[0].
I am using Python in VS2017 on Windows, and I used pyodbc instead of pymssql:
import pyodbc
conn_str = (
r"Driver={SQL Server Native Client 11.0};"
r"Server=.\SQLEXPRESS;"
r"Database=testing;"
r"Trusted_Connection=yes;"
)
conn = pyodbc.connect(conn_str)
cursor = conn.cursor()
cursor.execute('Select Distinct Name From Names')
results = cursor.fetchall()
conn.close()
my_file = open(r"C:\temp\output.txt","w")
for string in results:
print (string[0])
my_file.write(string[0] + "\n")
my_file.close()
Notice that I closed the database as soon as possible to keep things clean, I used a full path to the file, and I had to use my_file.close() with the parentheses to make it work.
I need help identifying the following number format.
For example, the following number format in MIB:
0x94 0x78 = 2680
0x94 0x78 in binary: [1001 0100] [0111 1000]
It seems that if the MSB is 1, it means another character follows it. And if it is 0, it is the end of the number.
So the value 2680 is [001 0100] [111 1000], formatted properly is [0000 1010] [0111 1000]
What is this number format called and what's a good way for computing this besides bit manipulation and shifting to a larger unsigned integer?
I have seen this called either 7bhm (7-bit has-more) or VLQ (variable length quantity); see http://en.wikipedia.org/wiki/Variable-length_quantity
This is stored big-endian (most significant byte first), as opposed to the C# BinaryReader.Read7BitEncodedInt method described at Encoding an integer in 7-bit format of C# BinaryReader.ReadString
I am not aware of any method of decoding other than bit manipulation.
Sample PHP code can be found at
http://php.net/manual/en/function.intval.php#62613
or in Python I would do something like
def encode_7bhm(i):
o = [ chr(i & 0x7f) ]
i /= 128
while i > 0:
o.insert(0, chr(0x80 | (i & 0x7f)))
i /= 128
return ''.join(o)
def decode_7bhm(s):
o = 0
for i in range(len(s)):
v = ord(s[i])
o = 128*o + (v & 0x7f)
if v & 0x80 == 0:
# found end of encoded value
break
else:
# out of string, and end not found - error!
raise TypeError
return o