CMS (PKCS#7) RecipientInfo - c

I am actually working on a function which should extract RecipientInfo from PKCS7 mime encrypted message. The reason why I want to do this is, that I want to get all mail addresses (or at least the keyids/fingerprints) the message is encrypted for.
Well - I tried something out and created something like this (indata is a *.p7m attachment content, indata_len the strlen of indata):
char *indata;
int indata_len, i;
PKCS7 *p7 = NULL;
BIO *bcont = NULL;
CMS_ContentInfo *cms = NULL;
STACK_OF(CMS_RecipientInfo) *recipients = NULL;
CMS_RecipientInfo *recip = NULL;
BIO *encMessage = BIO_new(BIO_s_mem());
if (encMessage == NULL) {
goto clean_exit;
}
if(!BIO_write(encMessage, indata, indata_len)) {
goto clean_exit;
}
cms = SMIME_read_CMS(encMessage,NULL);
if (cms == NULL ) {
goto clean_exit;
}
recipients = CMS_get0_RecipientInfos(cms);
if (recipients == NULL) {
goto clean_exit;
}
for (i=0; i< sk_CMS_RecipientInfo_num(recipients); i++) {
recip = sk_CMS_RecipientInfo_value(recipients, i);
if( recip == NULL || CMS_RecipientInfo_type(recip) != CMS_RECIPINFO_TRANS ) {
continue;
}
int r;
ASN1_OCTET_STRING **keyid;
X509_NAME **issuer;
ASN1_INTEGER **sno;
r = CMS_RecipientInfo_ktri_get0_signer_id(recip, keyid, issuer, sno);
if (!r) {
continue;
}
printf("Key: %s\n", keyid);
}
I get no error (checked with ERR_get_error()) but keyid, issuer and sno stay "null", output of above code is:
Key: (null)
So my question is, is it even possible to get that information of an encrypted message or is there just an error in reasoning on my side?
If it is possible to get that data, can someone give me a hint?
If it is not possible, whats the default (best) way to check which private key to use for decryption. Since there can be more than one S/Mime certificate/key for a single user. E.g. creating new key since the old one is lost or just get a new cert/key combination from provider, ...
Imho, looping through all keys could take some time if the message is really big.
Best regards,
Max

I don't know how to fix your code, but I have a couple of openssl commands and a python script to solve your task:
You can run the following command to get the list of all serial numbers
of the recipient keys in an encrypted file MYMAIL:
openssl smime -pk7out -inform DER -in MYMAIL \
| openssl pkcs7 -noout -print \
| grep serial
This will print the serial number as decimal numbers of all recipients, i.e. serial numbers of certificates for which the file MYMAIL has been encrypted for. For a given certificate file CERTFILE.0, the command
openssl x509 -in CERTFILE.0 -serial -noout
prints its serial number as a hexadecimal number. Now, you can to combine the serial numbers of the certificates you have with the serial numbers mentioned in MYMAIL.
I've wrote a python script that does this and that can be used to replace the default smime_decrypt_command in mutt, such that when decrypting an E-Mail, the correct private key is chosen for decryption: https://github.com/t-wissmann/dotfiles/blob/master/utils/smime-recipient-list.py
For the case that the url breaks, I'm pasting the entire script below.
#!/usr/bin/env python3
"""
Given an smime encrypted file and some smime certificates,
tell for which of the smime certificates, the encrypted file has been
encrypted for.
"""
import argparse
import os
import re
import subprocess
import sys
import textwrap
class Openssl:
def __init__(self, openssl_command):
self.openssl_command = openssl_command
def get_certificate_serial_number(self, certificate_file):
"""Given a certificate_file filepath, return its serial number as an int"""
command = [self.openssl_command, 'x509', '-in', certificate_file, '-serial', '-noout']
proc = subprocess.run(command, stdout=subprocess.PIPE)
# output should be of the form 'serial=HEXADECIMALNUMBER'
try:
return int(proc.stdout.decode().replace('serial=', ''), 16)
except ValueError:
print("Can not read file: {}".format(certificate_file), file=sys.stderr)
def smime_pk7out(self, encrypted_file):
"""run smime -pk7out, return its output"""
command = [self.openssl_command, 'smime', '-pk7out']
command += ['-inform', 'DER', '-in', encrypted_file]
proc = subprocess.run(command, stdout=subprocess.PIPE)
return proc.stdout.decode()
def pkcs7_serial_numbers(self, pk7buf):
"""extract all serial numbers via openssl pkcs7 -noout -print"""
command = [self.openssl_command, 'pkcs7', '-noout', '-print']
proc = subprocess.run(command, stdout=subprocess.PIPE, text=True, input=pk7buf)
for match in re.finditer('serial: ([0-9]+)', proc.stdout):
yield int(match.group(1))
def list_recipient_serial_numbers(self, encrypted_file):
"""Do essentially:
openssl smime -pk7out -inform DER -in MYMAIL \
| openssl pkcs7 -noout -print \
| grep serial
"""
pk7out = self.smime_pk7out(encrypted_file)
return list(self.pkcs7_serial_numbers(pk7out))
def smime_decrypt(self, private_key, certificate, filepath, passin='stdin'):
"""encrypt the given filepath and print to stdout"""
command = [self.openssl_command, 'smime', '-decrypt', '-passin', passin]
command += ['-inform', 'DER', '-in', filepath]
command += ['-inkey', private_key]
command += ['-recip', certificate]
subprocess.run(command)
def main():
"""main"""
description = "Detect recipients of smime encrypted files"
epilog = textwrap.dedent(r"""
E.g. you can decrypt an email with the command that picks the
private key automatically:
{} \
--passin stdin --decrypt \
--private-key ~/.smime/keys/* \
-- mymail ~/.smime/certificates/*
If you use mutt, you can set
set smime_decrypt_command="\
~/path/to/smime-recipient-list.py --passin stdin --decrypt \
--private-key ~/.smime/keys/* \
-- %f ~/.smime/certificates/KEYPREFIX.*"
where KEYPREFIX is the prefix of your key (i.e. without the .0 or .1 suffix).
""".format(sys.argv[0]))
parser = argparse.ArgumentParser(
description=description,
epilog=epilog,
formatter_class=argparse.RawDescriptionHelpFormatter)
parser.add_argument('encryptedfile', help='the encrypted file')
parser.add_argument('certificates',
nargs='+',
help='the smime certificate files')
parser.add_argument('--openssl', default='openssl', help='openssl command name')
parser.add_argument('--list-serials', action='store_true',
help='list serial numbers of certifacts')
parser.add_argument('--print-path', action='store_true',
help='print path of recipient certificates')
parser.add_argument('--private-keys', nargs='*', default=[], help='private keys for decrypt')
parser.add_argument('--decrypt', action='store_true',
help='decrypt using one of the private keys passed.\
the key must have the same file name as the certificate.')
parser.add_argument('--passin', default='stdin',
help='default openssl -passin parameter for decrypt')
args = parser.parse_args()
openssl = Openssl(args.openssl)
# get the serial number of every smime-certfile:
serialnum2cert = {}
for i in args.certificates:
serialnum2cert[openssl.get_certificate_serial_number(i)] = i
if args.list_serials:
for serialnum, keyfile in serialnum2cert.items():
print("{} --> {}".format(keyfile, serialnum))
recipients = openssl.list_recipient_serial_numbers(args.encryptedfile)
if args.print_path or args.decrypt:
matching_keys = []
for i in recipients:
if i in serialnum2cert:
matching_keys.append(serialnum2cert[i])
if args.print_path:
for i in matching_keys:
print(i)
if args.decrypt:
private_keys = {}
for filepath in args.private_keys:
private_keys[os.path.basename(filepath)] = filepath
key_found = None
for fp in matching_keys:
if os.path.basename(fp) in private_keys:
priv_key_path = private_keys[os.path.basename(fp)]
# print("We can use {} and {}".format(priv_key_path, fp))
key_found = (priv_key_path, fp)
if key_found is None:
print("No matching private key found.", file=sys.stderr)
sys.exit(1)
openssl.smime_decrypt(key_found[0], key_found[1],
args.encryptedfile, passin=args.passin)
if __name__ == "__main__":
main()

Related

Unable to transcode from audio/l16;rate=48000;channel=1 to one of: audio/x-float-array; rate=16000; channels=1,

I am currently working on Softbanks' robot Pepper and I try to use Watson speech-to-text solution on Pepper's audio buffers remote streaming by using websocket protocol.
I used the answer to that former question NAO robot remote audio problems to find a way to access remotly pepper's audio buffers and that project https://github.com/ibm-dev/watson-streaming-stt to learn how to use websocket protocole to use watson streaming stt.
However, after I open my websocket application, I start sending buffers to watson and after a few sendings, I receive error: 'Unable to transcode from audio/l16;rate=48000;channel=1 to one of: audio/x-float-array; rate=16000; channels=1'
Each time I'm trying to send Pepper's audio buffer to watson, it is unable to understand it.
I compared data I send with data sent in watson streaming stt example (using pyaudio streaming from microphone instead of Pepper's buffer streaming) and I don't see any difference. Both time I'm pretty sure that I am sending a string containing raw chunks of bytes. Which is what Watson asks for in it documentation.
I try to send chunks of 8192 bytes with a sample rate of 48kHz and I can easily convert Pepper's audio buffer in hexa so I don't understand why Watson can't transcode it.
Here is my code:
# -*- coding: utf-8 -*-
#!/usr/bin/env python
import argparse
import base64
import configparser
import json
import threading
import time
from optparse import OptionParser
import naoqi
import numpy as np
import sys
from threading import Thread
import ssl
import websocket
from websocket._abnf import ABNF
CHANNELS = 1
NAO_IP = "172.20.10.12"
class SoundReceiverModule(naoqi.ALModule):
"""
Use this object to get call back from the ALMemory of the naoqi world.
Your callback needs to be a method with two parameter (variable name, value).
"""
def __init__( self, strModuleName, strNaoIp):
try:
naoqi.ALModule.__init__(self, strModuleName );
self.BIND_PYTHON( self.getName(),"callback" );
self.strNaoIp = strNaoIp;
self.outfile = None;
self.aOutfile = [None]*(4-1); # ASSUME max nbr channels = 4
self.FINALS = []
self.RECORD_SECONDS = 20
self.ws_open = False
self.ws_listening = ""
# init data for websocket interfaces
self.headers = {}
self.userpass = "" #userpass and password
self.headers["Authorization"] = "Basic " + base64.b64encode(
self.userpass.encode()).decode()
self.url = ("wss://stream.watsonplatform.net//speech-to-text/api/v1/recognize"
"?model=fr-FR_BroadbandModel")
except BaseException, err:
print( "ERR: abcdk.naoqitools.SoundReceiverModule: loading error: %s" % str(err) );
# __init__ - end
def __del__( self ):
print( "INF: abcdk.SoundReceiverModule.__del__: cleaning everything" );
self.stop();
def start( self ):
audio = naoqi.ALProxy( "ALAudioDevice", self.strNaoIp, 9559 );
self.nNbrChannelFlag = 3; # ALL_Channels: 0, AL::LEFTCHANNEL: 1, AL::RIGHTCHANNEL: 2; AL::FRONTCHANNEL: 3 or AL::REARCHANNEL: 4.
self.nDeinterleave = 0;
self.nSampleRate = 48000;
audio.setClientPreferences( self.getName(), self.nSampleRate, self.nNbrChannelFlag, self.nDeinterleave ); # setting same as default generate a bug !?!
audio.subscribe( self.getName() );
#openning websocket app
self._ws = websocket.WebSocketApp(self.url,
header=self.headers,
on_open = self.on_open,
on_message=self.on_message,
on_error=self.on_error,
on_close=self.on_close)
sslopt={"cert_reqs": ssl.CERT_NONE}
threading.Thread(target=self._ws.run_forever, kwargs = {'sslopt':sslopt}).start()
print( "INF: SoundReceiver: started!" );
def stop( self ):
print( "INF: SoundReceiver: stopping..." );
audio = naoqi.ALProxy( "ALAudioDevice", self.strNaoIp, 9559 );
audio.unsubscribe( self.getName() );
print( "INF: SoundReceiver: stopped!" );
print "INF: WebSocket: closing..."
data = {"action": "stop"}
self._ws.send(json.dumps(data).encode('utf8'))
# ... which we need to wait for before we shutdown the websocket
time.sleep(1)
self._ws.close()
print "INF: WebSocket: closed"
if( self.outfile != None ):
self.outfile.close();
def processRemote( self, nbOfChannels, nbrOfSamplesByChannel, aTimeStamp, buffer ):
"""
This is THE method that receives all the sound buffers from the "ALAudioDevice" module"""
print "receiving buffer"
# self.data_to_send = self.data_to_send + buffer
# print len(self.data_to_send)
#self.data_to_send = ''.join( [ "%02X " % ord( x ) for x in buffer ] ).strip()
self.data_to_send = buffer
#print("buffer type :", type(data))
#print("buffer :", buffer)
#~ print( "process!" );
print( "processRemote: %s, %s, %s, lendata: %s, data0: %s (0x%x), data1: %s (0x%x)" % (nbOfChannels, nbrOfSamplesByChannel, aTimeStamp, len(buffer), buffer[0],ord(buffer[0]),buffer[1],ord(buffer[1])) );
if self.ws_open == True and self.ws_listening == True:
print "sending data"
self._ws.send(self.data_to_send, ABNF.OPCODE_BINARY)
print "data sent"
#print self.data_to_send
aSoundDataInterlaced = np.fromstring( str(buffer), dtype=np.int16 );
#
aSoundData = np.reshape( aSoundDataInterlaced, (nbOfChannels, nbrOfSamplesByChannel), 'F' );
# print "processRemote over"
# processRemote - end
def on_message(self, ws, msg):
print("message")
data = json.loads(msg)
print data
if "state" in data:
if data["state"] == "listening":
self.ws_listening = True
if "results" in data:
if data["results"][0]["final"]:
self.FINALS.append(data)
# This prints out the current fragment that we are working on
print(data['results'][0]['alternatives'][0]['transcript'])
def on_error(self, ws, error):
"""Print any errors."""
print(error)
def on_close(self, ws):
"""Upon close, print the complete and final transcript."""
transcript = "".join([x['results'][0]['alternatives'][0]['transcript']
for x in self.FINALS])
print("transcript :", transcript)
self.ws_open = False
def on_open(self, ws):
"""Triggered as soon a we have an active connection."""
# args = self._ws.args
print "INF: WebSocket: opening"
data = {
"action": "start",
# this means we get to send it straight raw sampling
"content-type": "audio/l16;rate=%d;channel=1" % self.nSampleRate,
"continuous": True,
"interim_results": True,
# "inactivity_timeout": 5, # in order to use this effectively
# you need other tests to handle what happens if the socket is
# closed by the server.
"word_confidence": True,
"timestamps": True,
"max_alternatives": 3
}
# Send the initial control message which sets expectations for the
# binary stream that follows:
self._ws.send(json.dumps(data).encode('utf8'))
# Spin off a dedicated thread where we are going to read and
# stream out audio.
print "INF: WebSocket: opened"
self.ws_open = True
def version( self ):
return "0.6";
def main():
"""initialisation
"""
parser = OptionParser()
parser.add_option("--pip",
help="Parent broker port. The IP address or your robot",
dest="pip")
parser.add_option("--pport",
help="Parent broker port. The port NAOqi is listening to",
dest="pport",
type="int")
parser.set_defaults(
pip=NAO_IP,
pport=9559)
(opts, args_) = parser.parse_args()
pip = opts.pip
pport = opts.pport
# We need this broker to be able to construct
# NAOqi modules and subscribe to other modules
# The broker must stay alive until the program exists
myBroker = naoqi.ALBroker("myBroker",
"0.0.0.0", # listen to anyone
0, # find a free port and use it
pip, # parent broker IP
pport) # parent broker port
"""fin initialisation
"""
global SoundReceiver
SoundReceiver = SoundReceiverModule("SoundReceiver", pip) #thread1
SoundReceiver.start()
try:
while True:
time.sleep(1)
print "hello"
except KeyboardInterrupt:
print "Interrupted by user, shutting down"
myBroker.shutdown()
SoundReceiver.stop()
sys.exit(0)
if __name__ == "__main__":
main()
I would be thankful if anyone had any idea on how to bypass that error or on what to try to get useful info. I first believed that I was sending "wrong" data to watson however after lots of attempts I have no clue on how to fix that problem.
Thank you a lot,
Alex

How to fetch SSL cert subject, issuer, start date and expire date from the trust.p12 cert file

Environment - IBM websphere application server 8.5.5
File - trust.p12 and key.p12 (in trust.p12 , 20 certificates are
added)
by using openssl commnd, i can able to see complete certificate
details like below
MAC Iteration 2048 MAC verified OK PKCS7 Encrypted data:
pbeWithSHA1And40BitRC2-CBC, Iteration 2048 Certificate bag Bag
Attributes
localKeyID: XX XX XX XX XX XX XX XX XX XX XX XX XX 48 54 A0 47 88 1D 90
friendlyName: test-server subject=/C=US/ST=IC/L=test/O=XXX Security/OU=XXX/CN=something1 issuer=/C=US/ST=IC/L=test/O=XXX
Security/OU=XXXX/CN=something1
-----BEGIN CERTIFICATE----- ... ... ...
-----END CERTIFICATE-----
Certificate bag Bag Attributes
localKeyID: XX XX XX XX XX XX XX XX
friendlyName: root subject=/C=US/ST=IC/L=test/O=XXX /OU=XXX/CN=testroot issuer=/C=US/ST=IC/L=test/O=XXX
/OU=XXXX/CN=testroot
-----BEGIN CERTIFICATE----- ... ... ...
-----END CERTIFICATE-----
But i tried to fetch subject, issuer, start date and expire date from
the trust.p12 cert file by using below commands.
1st Method
openssl pkcs12 -in trust.p12 -nokeys | openssl x509 -noout
-dates -subject -issuer -alias
2nd Method
openssl pkcs12 -in trust.p12 -out trust.pem -nodes
cat trust.pem | openssl x509 -noout -enddate
however i'm getting output for 1 certificate alone instead of 20
certificates trough above commands.
1) Is there any other way to fetch 20 certificate one by one something
like by passing alias name?
2) How to fetch subject, issuer, start date and expire date for 20 certificate one by one?
How about, if this could be done in java. You need to know the alias for all the 20 certificates and defined it as a string array.
Also you define alias as a config file so that if alias changes in future, you don't have to change the code.
static List<X509Certificate> certList = new ArrayList<>();
public static void main(String[] args) throws KeyStoreException
{
String[] alias = { "1","2"};
KeyStore keyStore = getKeyStore();
for (int i = 0; i < alias.length; i++) {
X509Certificate certFromKeyStore = (X509Certificate) keyStore.getCertificate(alias[i]);
System.out.println(certFromKeyStore.getSubjectDN());
certList.add(certFromKeyStore);
}
for (X509Certificate x509 : certList) {
// verify all the information you looking for
System.out.println(x509.getSerialNumber() + " "+ x509.getIssuerDN() );
}
}
public static KeyStore getKeyStore()
{
KeyStore keyStore = null;
try
{
keyStore = KeyStore.getInstance("PKCS12");
InputStream input = new FileInputStream("PATHTOP12");
keyStore.load(input, "YOUR_P12_PASSWORD".toCharArray());
} catch (Exception e)
{
// catch the exception
}
return keyStore;
}
Let me know if this helps.
Are you specifically looking this to be done in openssl ?

Wipe out dropout operations from TensorFlow graph

I have a trained freezed graph that I am trying to run on an ARM device. Basically, I am using contrib/pi_examples/label_image, but with my network instead of Inception. My network was trained with dropout, which now causes me troubles:
Invalid argument: No OpKernel was registered to support Op 'Switch' with these attrs. Registered kernels:
device='CPU'; T in [DT_FLOAT]
device='CPU'; T in [DT_INT32]
device='GPU'; T in [DT_STRING]
device='GPU'; T in [DT_BOOL]
device='GPU'; T in [DT_INT32]
device='GPU'; T in [DT_FLOAT]
[[Node: l_fc1_dropout/cond/Switch = Switch[T=DT_BOOL](is_training_pl, is_training_pl)]]
One solution I can see is to build such TF static library that includes the corresponding operation. From other hand, it might be a better idea to eliminate the dropout ops from the network in order to make it simpler and faster. Is there a way to do that?
Thanks.
#!/usr/bin/env python2
import argparse
import tensorflow as tf
from google.protobuf import text_format
from tensorflow.core.framework import graph_pb2
from tensorflow.core.framework import node_def_pb2
def print_graph(input_graph):
for node in input_graph.node:
print "{0} : {1} ( {2} )".format(node.name, node.op, node.input)
def strip(input_graph, drop_scope, input_before, output_after, pl_name):
input_nodes = input_graph.node
nodes_after_strip = []
for node in input_nodes:
print "{0} : {1} ( {2} )".format(node.name, node.op, node.input)
if node.name.startswith(drop_scope + '/'):
continue
if node.name == pl_name:
continue
new_node = node_def_pb2.NodeDef()
new_node.CopyFrom(node)
if new_node.name == output_after:
new_input = []
for node_name in new_node.input:
if node_name == drop_scope + '/cond/Merge':
new_input.append(input_before)
else:
new_input.append(node_name)
del new_node.input[:]
new_node.input.extend(new_input)
nodes_after_strip.append(new_node)
output_graph = graph_pb2.GraphDef()
output_graph.node.extend(nodes_after_strip)
return output_graph
def main():
parser = argparse.ArgumentParser()
parser.add_argument('--input-graph', action='store', dest='input_graph')
parser.add_argument('--input-binary', action='store_true', default=True, dest='input_binary')
parser.add_argument('--output-graph', action='store', dest='output_graph')
parser.add_argument('--output-binary', action='store_true', dest='output_binary', default=True)
args = parser.parse_args()
input_graph = args.input_graph
input_binary = args.input_binary
output_graph = args.output_graph
output_binary = args.output_binary
if not tf.gfile.Exists(input_graph):
print("Input graph file '" + input_graph + "' does not exist!")
return
input_graph_def = tf.GraphDef()
mode = "rb" if input_binary else "r"
with tf.gfile.FastGFile(input_graph, mode) as f:
if input_binary:
input_graph_def.ParseFromString(f.read())
else:
text_format.Merge(f.read().decode("utf-8"), input_graph_def)
print "Before:"
print_graph(input_graph_def)
output_graph_def = strip(input_graph_def, u'l_fc1_dropout', u'l_fc1/Relu', u'prediction/MatMul', u'is_training_pl')
print "After:"
print_graph(output_graph_def)
if output_binary:
with tf.gfile.GFile(output_graph, "wb") as f:
f.write(output_graph_def.SerializeToString())
else:
with tf.gfile.GFile(output_graph, "w") as f:
f.write(text_format.MessageToString(output_graph_def))
print("%d ops in the final graph." % len(output_graph_def.node))
if __name__ == "__main__":
main()
How about this as a more general solution:
for node in temp_graph_def.node:
for idx, i in enumerate(node.input):
input_clean = node_name_from_input(i)
if input_clean.endswith('/cond/Merge') and input_clean.split('/')[-3].startswith('dropout'):
identity = node_from_map(input_node_map, i).input[0]
assert identity.split('/')[-1] == 'Identity'
parent = node_from_map(input_node_map, node_from_map(input_node_map, identity).input[0])
pred_id = parent.input[1]
assert pred_id.split('/')[-1] == 'pred_id'
good = parent.input[0]
node.input[idx] = good

Handling Hebrew files and folders with Python 3.4

I used Python 3.4 to create a programm that goes through E-mails and saves specific attachments to a file server.
Each file is saved to a specific destination depending on the sender's E-mail's address.
My problem is that the destination folders and the attachments are both in Hebrew and for a few attachments I get an error that the path does not exsist.
Now that's not possible because It can fail for one attachment but not for the others on the same Mail (the destination folder is decided by the sender's address).
I want to debug the issue but I cannot get python to display the file path it is trying to save correctly. (it's mixed hebrew and english and it always displays the path in a big mess, although it works correctly 95% of the time when the file is being saved to the file server)
So my questions are:
what should I add to this code so that it will proccess Hewbrew correctly?
Should I encode or decode somthing?
Are there characters I should avoid when proccessing the files?
here's the main piece of code that fails:
try:
found_attachments = False
for att in msg.Attachments:
_, extension = split_filename(str(att))
# check if attachment is not inline
if str(att) not in msg.HTMLBody:
if extension in database[sender][TYPES]:
file = create_file(str(att), database[sender][PATH], database[sender][FORMAT], time_stamp)
# This is where the program fails:
att.SaveAsFile(file)
print("Created:", file)
found_attachments = True
if found_attachments:
items_processed.append(msg)
else:
items_no_att.append(msg)
except:
print("Error with attachment: " + str(att) + " , in: " + str(msg))
and the create file function:
def create_file(att, location, format, timestamp):
"""
process an attachment to make it a file
:param att: the name of the attachment
:param location: the path to the file
:param format: the format of the file
:param timestamp: the time and date the attachment was created
:return: return the file created
"""
# create the file by the given format
if format == "":
output_file = location + "\\" + att
else:
# split file to name and type
filename, extension = split_filename(att)
# extract and format the time sent on
time = str(timestamp.time()).replace(":", ".")[:-3]
# extract and format the date sent on
day = str(timestamp.date())
day = day[-2:] + day[4:-2] + day[:4]
# initiate the output file
output_file = format
# add the original file name where needed
output_file = output_file.replace(FILENAME, filename)
# add the sent date where needed
output_file = output_file.replace(DATE, day)
# add the time sent where needed
output_file = output_file.replace(TIME, time)
# add the path and type
output_file = location + "\\" + output_file + "." + extension
print(output_file)
# add an index to the file if necessary and return it
index = get_file_index(output_file)
if index:
filename, extension = split_filename(output_file)
return filename + "(" + str(index) + ")." + extension
else:
return output_file
Thanks in advance, I would be happy to explain more or supply more code if needed.
I found out that the promlem was not using Hebrew. I found that there's a limit on the number of chars that the (path + filename) can hold (255 chars).
The files that failed excided that limit and that caused the problem

openssl Diffie Hellman public key to pem

I'm buiding a system using openssl.
We're going to use Diffie Hellman to share information between parties.
I had been able to create a DH using openssl.
Now I want to send the public key to the client using PEM format but I cannot find any function to convert DH public key to PEM format.
Anyone knows how to do this conversion?
Here you have the code I use to generate the DH structure:
BIGNUM * p = NULL, * g = NULL;
//Create DH MOD Group
DH * dh = dh_new_group14();
if (!dh)
puts("DH_new failed");
//Check everything is OK
int codes = 0;
if (!DH_check(dh, &codes))
puts("DH_check failed");
//Generate DH key
if (!DH_generate_key(dh))
puts("DH_generate_key failed");
I'm also capable of building a ASN1_INTEGER structure, but again I cannot find any function to generate the PEM from this structure.
Ok, I think I'm getting close.
I've managed to get an example with Java and what it generates is:
SEQUENCE {
SEQUENCE {
OBJECTIDENTIFIER 1.2.840.113549.1.3.1
SEQUENCE {
INTEGER 0x00ffffffffffffffffc90fdaa22168c234c4c6628b80dc1cd129024e088a67cc74020bbea63b139b22514a08798e3404ddef9519b3cd3a431b302b0a6df25f14374fe1356d6d51c245e485b576625e7ec6f44c42e9a637ed6b0bff5cb6f406b7edee386bfb5a899fa5ae9f24117c4b1fe649286651ece45b3dc2007cb8a163bf0598da48361c55d39a69163fa8fd24cf5f83655d23dca3ad961c62f356208552bb9ed529077096966d670c354e4abc9804f1746c08ca18217c32905e462e36ce3be39e772c180e86039b2783a2ec07a28fb5c55df06f4c52c9de2bcbf6955817183995497cea956ae515d2261898fa051015728e5a8aacaa68ffffffffffffffff
INTEGER 0x02 (2 decimal)
}
}
BITSTRING 0x0282010100b9c13521bc982e69de3e139d2521f32187ca932fdb579344c37cf2a8effb1c589ac27446656c911aefb84c961be5c389cabae7012b9edbec439ce5b57df4ad427e8baaa334c18c8bbf0fc3b19b197d484ae174f3fb538183368cdb11ecc228fc3fbb0029ff9aa0c06ccebbba47c1d1208410e9506cc08ae3bdc71924e95ae74994268822637ad628af95cf8b09cba0e070c7a8126921f6a700792ef45d844b8812f4d67f19bbc809ad33ac1ea59f4e3a9542e26b3a5f1738de6b9f8092c5a323747a716f39a17f879b87981c00944c8e5fb8f1e4d5ace6c81c182f80711bc55865c8562688b7084ae42f706fb80081f9e97982ef0242df221b202cee9b9ffcaf : 0 unused bit(s)
}
But what I get using PEM_write_bio_DHparams is almost the same but without the BITSTRING and the OBJECTIDENTIFIER.
SEQUENCE {
INTEGER 0x00ffffffffffffffffc90fdaa22168c234c4c6628b80dc1cd129024e088a67cc74020bbea63b139b22514a08798e3404ddef9519b3cd3a431b302b0a6df25f14374fe1356d6d51c245e485b576625e7ec6f44c42e9a637ed6b0bff5cb6f406b7edee386bfb5a899fa5ae9f24117c4b1fe649286651ece45b3dc2007cb8a163bf0598da48361c55d39a69163fa8fd24cf5f83655d23dca3ad961c62f356208552bb9ed529077096966d670c354e4abc9804f1746c08ca18217c32905e462e36ce3be39e772c180e86039b2783a2ec07a28fb5c55df06f4c52c9de2bcbf6955817183995497cea956ae515d2261898fa051015728e5a8aacaa68ffffffffffffffff
INTEGER 0x02 (2 decimal)
}
Any clue about where's the problem?
I've seen that Java version generates a X.509 certificate to send the data, maybe I should generate a X509 certificate from the DH on my c++ version?
I think public keys are stored not alone but inside certificate request (csr) or certificate. So, you can use either PEM_write_bio_X509_REQ() or PEM_write_bio_X509() to store them in PEM format. Results will:
Certificate Request:
Data:
Version: 0 (0x0)
Subject: CN=DH Server Certificate (DSA-signed)
Subject Public Key Info:
Public Key Algorithm: dhKeyAgreement
PKCS#3 DH Public-Key: (1024 bit)
public-key:
00:ad:0c:c3:73:26:1b:68:2e:b2:1f:36:0c:eb:3c:
0b:bb:62:b2:fd:ac:8a:92:97:b9:79:6f:1a:f9:2e:
20:21:ff:fd:c4:e2:70:2a:62:ad:62:fc:67:d8:33:
58:09:19:8f:92:a3:b8:5b:41:30:d7:a9:b9:49:01:
07:24:76:ec:f9:88:e6:58:4e:a7:21:83:a4:a8:18:
4e:9a:ca:c5:14:04:9d:85:65:ee:7b:6a:59:80:af:
5e:fd:56:34:3e:95:34:14:64:0c:99:2e:c7:cc:4d:
9f:60:0f:a2:18:60:80:fe:6f:ed:4a:45:f3:4e:49:
97:42:a2:ec:86:c4:fd:5e:e9
prime:
00:e6:7f:e7:4b:4c:5a:55:bf:5e:2d:42:5d:17:62:
f0:6f:ff:d2:55:3f:18:a1:9e:51:02:34:ac:2b:64:
1b:c6:07:5f:ea:02:4f:f0:31:ed:71:ad:06:21:47:
4b:36:2a:65:a0:2a:dc:fb:3a:6f:24:6f:fc:4a:67:
0a:50:eb:6d:73:a3:35:fd:6a:d8:2d:68:b4:f2:c5:
c1:0b:6e:a1:5a:49:47:d6:bc:ab:9c:3f:d2:7a:7b:
2a:cf:be:2b:34:7e:0c:4f:00:0d:20:3e:83:6e:f3:
6c:65:f6:f0:f5:2a:5d:5f:1a:f2:c1:86:b6:0c:44:
19:1e:b0:66:ee:ea:eb:83:73
generator: 2 (0x2)
Attributes:
a0:00
Signature Algorithm: itu-t
-----BEGIN CERTIFICATE REQUEST-----
MIIBZDCCAVgCAQAwLTErMCkGA1UEAxMiREggU2VydmVyIENlcnRpZmljYXRlIChE
U0Etc2lnbmVkKTCCASAwgZUGCSqGSIb3DQEDATCBhwKBgQDmf+dLTFpVv14tQl0X
YvBv/9JVPxihnlECNKwrZBvGB1/qAk/wMe1xrQYhR0s2KmWgKtz7Om8kb/xKZwpQ
621zozX9atgtaLTyxcELbqFaSUfWvKucP9J6eyrPvis0fgxPAA0gPoNu82xl9vD1
Kl1fGvLBhrYMRBkesGbu6uuDcwIBAgOBhQACgYEArQzDcyYbaC6yHzYM6zwLu2Ky
/ayKkpe5eW8a+S4gIf/9xOJwKmKtYvxn2DNYCRmPkqO4W0Ew16m5SQEHJHbs+Yjm
WE6nIYOkqBhOmsrFFASdhWXue2pZgK9e/VY0PpU0FGQMmS7HzE2fYA+iGGCA/m/t
SkXzTkmXQqLshsT9XumgADADBgEAAwEA
-----END CERTIFICATE REQUEST-----
and
Certificate:
Data:
Version: 1 (0x0)
Serial Number: 1407830109 (0x53e9c85d)
Signature Algorithm: dsaWithSHA1
Issuer: CN=DSA Server Certificate
Validity
Not Before: Aug 12 07:55:14 2014 GMT
Not After : Aug 9 07:55:14 2024 GMT
Subject: CN=DH Server Certificate (DSA-signed)
Subject Public Key Info:
Public Key Algorithm: dhKeyAgreement
PKCS#3 DH Public-Key: (1024 bit)
public-key:
00:ad:0c:c3:73:26:1b:68:2e:b2:1f:36:0c:eb:3c:
0b:bb:62:b2:fd:ac:8a:92:97:b9:79:6f:1a:f9:2e:
20:21:ff:fd:c4:e2:70:2a:62:ad:62:fc:67:d8:33:
58:09:19:8f:92:a3:b8:5b:41:30:d7:a9:b9:49:01:
07:24:76:ec:f9:88:e6:58:4e:a7:21:83:a4:a8:18:
4e:9a:ca:c5:14:04:9d:85:65:ee:7b:6a:59:80:af:
5e:fd:56:34:3e:95:34:14:64:0c:99:2e:c7:cc:4d:
9f:60:0f:a2:18:60:80:fe:6f:ed:4a:45:f3:4e:49:
97:42:a2:ec:86:c4:fd:5e:e9
prime:
00:e6:7f:e7:4b:4c:5a:55:bf:5e:2d:42:5d:17:62:
f0:6f:ff:d2:55:3f:18:a1:9e:51:02:34:ac:2b:64:
1b:c6:07:5f:ea:02:4f:f0:31:ed:71:ad:06:21:47:
4b:36:2a:65:a0:2a:dc:fb:3a:6f:24:6f:fc:4a:67:
0a:50:eb:6d:73:a3:35:fd:6a:d8:2d:68:b4:f2:c5:
c1:0b:6e:a1:5a:49:47:d6:bc:ab:9c:3f:d2:7a:7b:
2a:cf:be:2b:34:7e:0c:4f:00:0d:20:3e:83:6e:f3:
6c:65:f6:f0:f5:2a:5d:5f:1a:f2:c1:86:b6:0c:44:
19:1e:b0:66:ee:ea:eb:83:73
generator: 2 (0x2)
Signature Algorithm: dsaWithSHA1
r:
30:1c:1d:8a:87:b3:83:de:b2:4b:a4:1c:69:71:a1:
93:ae:1b:c0:30:0e:e0:b1:94:eb:92:da:e8:3b:12:
8c:59
s:
36:14:4c:fd:ce:a3:de:ef:6a:ac:49:45:b3:69:7d:
bf:98:72:9a:b0:6c:7b:59:bc:80:ee:96:32:a6:a3:
e8:e0
-----BEGIN CERTIFICATE-----
MIIB/zCCAacCBFPpyF0wCQYHKoZIzjgEAzAhMR8wHQYDVQQDExZEU0EgU2VydmVy
IENlcnRpZmljYXRlMB4XDTE0MDgxMjA3NTUxNFoXDTI0MDgwOTA3NTUxNFowLTEr
MCkGA1UEAxMiREggU2VydmVyIENlcnRpZmljYXRlIChEU0Etc2lnbmVkKTCCASAw
gZUGCSqGSIb3DQEDATCBhwKBgQDmf+dLTFpVv14tQl0XYvBv/9JVPxihnlECNKwr
ZBvGB1/qAk/wMe1xrQYhR0s2KmWgKtz7Om8kb/xKZwpQ621zozX9atgtaLTyxcEL
bqFaSUfWvKucP9J6eyrPvis0fgxPAA0gPoNu82xl9vD1Kl1fGvLBhrYMRBkesGbu
6uuDcwIBAgOBhQACgYEArQzDcyYbaC6yHzYM6zwLu2Ky/ayKkpe5eW8a+S4gIf/9
xOJwKmKtYvxn2DNYCRmPkqO4W0Ew16m5SQEHJHbs+YjmWE6nIYOkqBhOmsrFFASd
hWXue2pZgK9e/VY0PpU0FGQMmS7HzE2fYA+iGGCA/m/tSkXzTkmXQqLshsT9Xukw
CQYHKoZIzjgEAwNHADBEAiAwHB2Kh7OD3rJLpBxpcaGTrhvAMA7gsZTrktroOxKM
WQIgNhRM/c6j3u9qrElFs2l9v5hymrBse1m8gO6WMqaj6OA=
-----END CERTIFICATE-----
Have a look at what is done by the PEM_write_bio_DHparams() function, I think it does what you want.
[Edit: sorry, wrong function the first time]
Try this;
EVP is used for generic keys (keypairs)
BIO *b;
b = BIO_new(BIO_s_file());
BIO_set_fp(b, stdout, BIO_NOCLOSE);
EVP_PKEY *key = EVP_PKEY_new();
EVP_PKEY_assign_DH(key, DHAlice);
PEM_write_bio_PUBKEY(b, key);

Resources