0

So I have a secure messaging script written up that uses JSON to send messages between a client and server. At one point I'm generating signed message digests using SHA1 and this is giving me some characters that I can't parse in JSON.generate to send my messages in JSON format around. Can anyone help me get around this error "in `encode': "\xAB" from ASCII-8BIT to UTF-8 (Encoding::UndefinedConversionError)" ?

The main problem I'm having is with this section of code:

#make new private / public rsa key-pair
rsakey = OpenSSL::PKey::RSA.new 2048

#hash the key using sha1
sha1 = OpenSSL::Digest::SHA1.new
digest = sha1.digest(rsakey.public_key.to_pem)

pubkey = JSON.generate({
    key: rsakey.public_key.to_pem,
    digest: digest
    })

It's not allowing me to do a JSON.generate of digest. Does anyone know of a workaround or another way to encode my message digest?

My full code is below:

# encoding: utf-8
require 'socket'
require 'openssl'
require 'json'

port = 9090

s = TCPServer.open(port)

#make new private / public rsa key-pair
rsakey = OpenSSL::PKey::RSA.new 2048

#hash the key using sha1
sha1 = OpenSSL::Digest::SHA1.new
digest = sha1.digest(rsakey.public_key.to_pem)

pubkey = JSON.generate({
    key: rsakey.public_key.to_pem,
    digest: digest
    })

loop {
    client = s.accept
    #get public key from alice
    incoming = client.gets()
    alice = JSON.parse(incoming)
    alice_key = OpenSSL::PKey::RSA.new alice['key']

    #send public key to alice
    puts pubkey
    client.puts pubkey  

    #get encrypted package from alice
    json_full_package = client.gets()
    full_package = JSON.parse(json_full_package)

    #decrypt and print package  
    cipher = OpenSSL::Cipher.new("DES3")
    cipher.decrypt
    key = rsakey.private_decrypt(full_package['key'])
    iv = rsakey.private_decrypt(full_package['iv'])
    json_package = cipher.update(full_package['package'])

    package = JSON.parse(json_package)
    decrypted_digest = alice_key.public_decrypt(package['signed_digest'])
    sha1 = OpenSSL::Digest::SHA1.new
    digest = sha1.digest(package['data'])
    throw 'failed digest' unless digest == decrypted_digest

    puts package['data']
    client.close
}

# encoding: utf-8
require 'socket'
require 'openssl'
require 'json'

host = 'lab1-15.eng.utah.edu'
port = 9090

s = TCPSocket.open(host, port)

pubkey_q = false

keyF = File.new("public_key.pem", 'w')

#generate alice's key pair
key = OpenSSL::PKey::RSA.new 2048

to_bob_public = JSON.generate({
    key: key.public_key.to_pem
    })
s.send(to_bob_public)

#get public key certificate from bob
while line = s.gets
    puts line.chop
    bob = JSON.parse(line)
end
bob_key = OpenSSL::PKey::RSA.new bob['key']
bob_digest = bob['digest']

#verify public key
sha1 = OpenSSL::Digest::SHA1.new
t_digest = sha1.digest(bob['key'])
throw "not verified" unless t_digest == bob_digest

data = File.read('document') #data is original message

#hash the document using sha1
sha1 = OpenSSL::Digest::SHA1.new
digest = sha1.digest(data)

#sign with private key
signed_digest = key.private_encrypt(digest)

#package this in json
package = JSON.generate({
        signed_digest: signed_digest,
        data: data      
    })

#make cipher for encryption
cipher = OpenSSL::Cipher.new("DES3")
cipher.encrypt
key = cipher.random_key
iv = cipher.random_iv
#encrypt data
encrypted = cipher.update(package) 

#encrypt key and iv using bob's public key
encrypted_cipher_key = bob_key.public_encrypt(key)
encrypted_cipher_iv = bob_key.public_encrypt(iv)

full_package = JSON.generate({
        key: encrypted_cipher_key,
        iv: encrypted_cipher_iv,
        package: encrypted      
    })

#send full_package to bob
s.send(full_package)

s.close

1 Answer 1

1

Use #hexdigest instead of #digest and you'll get hex. Right now you're attempting to encode binary into JSON (as that's what #digest returns) and that is causing the encode failure.

Sign up to request clarification or add additional context in comments.

3 Comments

this worked, but now i'm getting the same problem for the line signed_digest = key.private_encrypt(digest) #package this in json package = JSON.generate({ signed_digest: signed_digest, data: data })
not sure how i should send a private_encrypted string through json, or if it's even possible
You can encode the binary data in a variety of ways, but one easy way would be base64. Just require 'base64' and then use Base64.encode64 to encode it (and decode64 to decode it).

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.