Gianni Giaccaglini

Tricks & mini applics on WPF
posts - 46, comments - 0, trackbacks - 0

Creare un documento segreto in due salse

   

Creare un documento segreto, in due salse

IN FONDO AL POST SI HA LA SOLUZIONE PIU' AUTOMATIZZATA

L’idea base consiste nell’inserire il testo segreto nell’Editor VBA di Word, più precisamente nel modulo ThisDocument del nostro ipotetico MioDocum.doc , ovvero non nella cartella Normal bensì in
Project(MioDocum) > Microsoft Word Oggetti > ThisDocument. Il documento all’apertura esibisce un testo-civetta che nulla a che fare con quello autentico, ospitato in una variabile di tipo stringa, dopo di che una macro opportuna lo trasferisce nel MioDocum.doc  al posto di quello fasullo.

Le due “salse” del titolo sono altrettante soluzioni che ho escogitato in momenti successivi.

  • La prima soluzione tiene conto soltanto dei caratteri virgola e Carriage Return che non potrebbero essere racchiusi tra virgolette. A meno di ardue complicanze (cui ho presto rinunciato) in tal modo si recupera solo del testo puro, perdendo formattazioni di ogni tipo, a partire dal grassetto, corsivo, colore e quant’altro.
  • La seconda, che mi è venuta in mente nottetempo, parecchi mesi dopo, consiste nel presentare un testo apparentemente crittografato ma formattato esattamente come l’originale.
  • una terza - variante della precedente - automatizza all'estremo i procedimenti escogitati nella seconda!

Prima soluzione

Per capire il trucco base, si deve partire dal fondo, ossia considerare una macro del genere:

Sub SvelaDocumento()

  If InputBox("Password?", "") <> "trentatre" Then Exit Sub

  Dim DocSegr As String

  DocSegr = "Testimonianza del Signor Mario Rossetti.<<CR>>In data 10/1/2012 ho incontrato in località Vattelapesca presso il locale Bar Sport il confidente Russo Giuseppe, che mi ha svelato in gran segreto quanto segue.<<CR>><<VIRG>>Questo e quello per me pari sono<<VIRG>>, concludendo con <<VIRG>>Chi vuol esser lieto sia, del diman non v'ha certezza<<VIRG>>.<<CR>>Letto, sottoscritto e approvato addì 10/2/2012.<<CR>>"

  With ThisDocument

    .Content = ""

    .Content = DocSegr

  End With

  RipristinaCRetVIRG ' Vedi più avanti

End Sub

Il documento segreto è, semplicemente, la stringa contenuta nella variabile DocSegr (per eccesso di fantasia) e va da sé che occorre che ciascuno fissi una password, anzi due: non solo la “trentatre” di cui sopra ma anche un’altra o la stessa, però relativa al progetto VBA, altrimenti il segreto appartiene al repertorio della maschera napoletana.

La visualizzazione viene effettuata da ThisDocument.Content=DocSegr , istruzione preceduta da una che annulla il Content attuale. Quest’ultimo sarà un testo fasullo a piacere.

OK, ma cosa sono quegli strani <<CR>> e <<VIRG>>? Come i più scafati avranno già compreso in una stringa la presenza di a-capo (CR, Carriage Return) e virgolette è possibile ma problematica, di qui l’idea di rappresentarle mediante le tag un po’speciali: <<CR>> e <<VIRG>>. A tale scopo, si pensi di partire digitando questo testo (chiedendo venia per la sua ridicola imitazione di un messaggio spionistico):

Testimonianza del Signor Mario Rossetti.

In data 10/1/2012 ho incontrato in località Vattelapesca presso il locale Bar Sport il confidente Russo Giuseppe, che mi ha svelato in gran segreto quanto segue.

"Questo e quello per me pari sono", concludendo con "Chi vuol esser lieto sia, del diman non v'ha certezza”.

Letto, sottoscritto e approvato addì 10/2/2012.

Per inserire le predette tag si ricorrerà a macrocodice opportuno. Eccolo:

Sub CreaTagCRetVIRG()

  If InputBox("Password?", "") <> "trentatre" Then Exit Sub

  If InStr(Me.Content, "<<") > 0 Then

    MsgBox "Le tag entro << e >> ci sono già!", vbExclamation, "Attenzione!"

    Exit Sub

  End If

  Me.Content = Replace(Me.Content, Chr(13), "<<CR>>")

  ' Quest'altra istruz. NON va, per misteriosi motivi

  ' Me.Content = Replace(Me.Content, Chr(10), "<<VIRG>>")

  Rimpiazza "^l", "<<LF>>"

  ' Quest'altra istruz. NON va, causa anomale virgolette di Word

  ' Me.Content = Replace(Me.Content, Chr(34), "<<VIRG>>")

  Rimpiazza """", "<<VIRG>>"

End Sub

 

Private Sub Rimpiazza(Car1 As String, Car2 As String)

  With Selection.Find

    .Text = Car1

    .Replacement.Text = Car2

    .Execute Replace:=wdReplaceAll

  End With

End Sub

 

Nota. Le istruzioni in neretto sono quelle che eseguono la sostituzione delle tag, tra cui si noti quella relativa ai linefeed, con <<LF>>.

Dimenticavo la macro che ripristina i normali CR, LF e virgolette? Niente affatto:

Private Sub RipristinaCRetVIRG()

  ' Selection.Find.ClearFormatting

  ' Selection.Find.Replacement.ClearFormatting

  Rimpiazza "<<CR>>", "^p"

  Rimpiazza "<<LF>>", "^l"

  Rimpiazza "<<VIRG>>", """"

  ' Selection.Find.Execute Replace:=wdReplaceAll

End Sub

 

Se si rivede la SvelaDocumento si noterà che al suo termine viene evocata RipristinaCRetVIRG.

Conclusioni. Il metodo è ma palesemente ha due limiti:

1)      L’assegnazione del testo segreto alla variabile DocSegr della macro SvelaDocumento va eseguita a mano, non c’è altro da fare ;

2)      formati, stili per non dire immagini non vengono supportati; magari qualcosa si può fare con le tabelle, operazione che si presenta quantomeno macchinosa.

Nota. Un’altra possibilità avanzata potrebbe forse scaturire dall’uso del formato Open XML di Word ultima edizione (file .docm), visto che separa contenuti e formati?

 

Per chiudere ecco un testo fasullo che do in pasto ai miei 24 lettori, sperando che apprezzino questa delicata lirica di Salvatore Di Giacomo.

Pianefforte ‘e notte

Nu pianefforte ‘e notte
Sona lontanamente
E ‘a musica se sente
Pe ll’aria suspirà.

È ll’una: dorme ‘o vico
Ncoppa ’a sta nonna nonna
È nu mutivo antico
‘E tanto tempo fa.
Dio, quanta stelle ‘n cielo!
Che luna! E c’aria doce!
Quanto na bella voce
Vurria sentì cantà!
Ma solitario e lento
More ‘o mutivo antico;
se fa cchiù cupo ‘o vico
dint’a all’oscurità.
Ll’anema mia surtanto
Rummane a sta fenesta.
Aspetta ancora. E resta,
Ncantannose, a penzà.

Seconda soluzione

Ecco un ipotetico documento, in chiaro. Semplice e ridotto ma comprendente grassetti, sottolineature ecc., nonché una tabella.

AMBA
rABà

Ciccì    Coc

 

tre civette

Sul comò

 

Il nuovo procedimento rinuncia all’utilizzo degli oggetti “a distanza” – caratteri, paragrafi ecc. – sfruttando invece le istruzioni volgari fornite dal registratore - tipicamente Selection.MoveRigth -, in quanto esse rispettano i vari formati.

La seguente routine provvede all’occultamente. Come facilmente si scopre lanciandola, essa mantiene i formati ma modifica i vari caratteri in modo da far pensare che si tratti di un testo crittografato. Che però è del tutto privo di significato.

Sub CelaDocum()

  Dim TuttiCar As Characters

  Set TuttiCar = ThisDocument.Characters

  Dim CodCar As String, i As Long

  Selection.HomeKey unit:=wdStory

  For i = 1 To TuttiCar.Count

    CodCar = Asc(Selection)

    ' Ignora virgolette, spazi e caratteri strani

    If CodCar = 34 Or CodCar <= 32 Then

      Selection.MoveRight unit:=wdCharacter, Count:=1

    Else

      Selection.MoveRight unit:=wdCharacter, Count:=1, Extend:=wdExtend

      Randomize

      CodCar = 33 + Int(Rnd * 146)

      Selection.TypeText Chr(CodCar)

    End If

  Next

End Sub

Ecco come si presenta il testo pseudo crittografico, un guazzabuglio che farà ammattire, senza successo, i soloni della decrittazione!:

J
/Z
'

;:[43    r•G

 

.:‚ ¦ž@sk‚-

$5* K˜:

 

Commenti essenziali. L’istruzione cruciale è quella evidenziata in giallo, che discrimina i caratteri virgolette (codice ASCII 34) e quelli che precedono gli spazi (ASCII 32), nel qual caso il cursore si sposta a destra senza selezione. In caso contrario (Else) lo spostamento destrorso avviene con selezione (Extend:=wdExtend) e su tale selezione il metodo TypeText provvede a inserire un carattere pseudo-casuale.

Nota. In realtà di solito Word sulla digitazione dell’utente inserisce virgolette aperte (ASCII e chiuse – come nel caso Dissi: “Ciao”. Dunque il problema si presenta di rado, ma non può essere ignorato, putacaso con il listato di un programma.

La procedura di ripristino SvelaDocum permette di riottenere il documento verace, attingendolo da una stringa DocSegr, come già visto nella versione precedente, però conservando formati e tabelle.

Sub SvelaDocum()

  If InputBox("Password?", "Per decrittare") <> "trentatre" Then

    On Error Resume Next

    Application.DisplayAlerts = wdAlertsNone

    Me.Close

    Exit Sub

  End If

  Dim DocSegr As String

  DocSegr = _

  "AMBArABàCicci    CoccòTre civettesul comò"

  Dim TuttiCar As Characters

  Set TuttiCar = ThisDocument.Characters

  Dim CodCar As String, i As Long

  Dim j As Long ' Indice carattere di TestoOrig

  Selection.HomeKey unit:=wdStory

  For i = 1 To TuttiCar.Count

    CodCar = Asc(Selection)

'   Ignora virgolette, spazi e caratteri strani

'   IMP! Con <= si ha errore (duplicazione spazi)

    If CodCar = 34 Or CodCar < 32 Then '

      Selection.MoveRight unit:=wdCharacter, Count:=1

    Else

      Selection.MoveRight unit:=wdCharacter, Count:=1, Extend:=wdExtend

      j = j + 1

      Selection.TypeText Mid(TestoOrig, j, 1)

    End If

  Next

End Sub

Commenti essenziali. Dopo quanto detto a proposito della precedente procedura mi limito a dire che la sostituzione dei caratteri pseudo-crittati avviene pescando con l’indice j nella variabile stringa DocSegr. Si noti inoltre la variante cattiva sulla richiesta della password, che sulla discrepanza rispetto a quella prevista chiude brutalmente il documento.

Piuttosto si esamini la seguente, che serve proprio a creare la famosa stringa segreta, inserendola al termine in un documento appositamente creato ex novo.

Sub CreaStringaDocum()

  Dim StringaDoc As String

  Dim TuttiCar As Characters

  Set TuttiCar = ThisDocument.Characters

  Dim car As String

  For i = 1 To TuttiCar.Count

    car = TuttiCar(i)

    If Asc(car) <> 34 Then ' Escludi le virgolette

      If Asc(car) >= 32 Then

        DocSegr = DocSegr & car

      End If

    End If

  Next

  MsgBox DocSegr ' Usato per debug

  Documents.Add  ' Crea un nuovo Documento1 (o Documento2 ...)

  Selection.TypeText Text:= DocSegr ' Inseriscivi DocSegr

End Sub

Commenti essenziali. Resta il compito, affidato a un utente consapevole e con un minimo di competenza VBA, di copiare manualmente il testo del Documento1 e inserirlo a fianco dell’istruzione DocSegr =  della procedura SvelaDocum e infine chiudere senza salvarlo il neonato documento. Sempre a mano.

Le manovre necessarie per impedire la visualizzazione del codice VBA sono lasciate a quanti fossero interessati a mettere in pratica queste strambe (ma curiose) soluzioni, cui ricordo che dovrebbero dichiarare come Private tutte le routine, salvo SvelaDocum, che così sarà l’unica accessibile con Alt+F8. Dopo di che solo l'utente che conosce la password può vedere il documento... come mamma lo fece, vestito di tutte le sue belle formattazioni.

Se lo si trasmette come allegato di una mail...  il gioco è fatto.

Se infine si vuol provare il file Documento segreto.doc lo si può scaricare, zippato, da:

http://www.giannigiaccaglini.it/download/docsegr.zip

Unzippare, servire caldo, premere Alt+F8 e vedere, non di nascosto, l’effetto che fa.

 

SOLUZIONE ULTIM’ORA: eureka!

Pensa e ripensa, alla fine ho risolto felicemente il problema di automatizzare al massimo la creazione della stringa TestoOrig evitando sia di parcheggiarla in un nuovo Documento1 sia di obbligare l’utente al copia & incolla manuale nella istruzione TestoOrig =... della routine SvelaDocum.

Mi sono infatti ricordato che esiste una possibilità avanzata – ignota a tutti o quasi – che permette modifiche dinamiche di ogni tipo nel codice VBA. Il marchingegno va sotto l’acronimo VBIDE, di cui tralascio i dettagli. Basti sapere che per fruirne occorre nell’Editor VB scegliere Strumenti > Riferimenti... quindi fissare Microsoft Visual Basic for Applications Exsgtensibility 5.3. Dopo di ché si possono compiere le più spericolate operazioni, come creare ex novo UserForm, Moduli e molto altro. Nel nostro caso occorre semplicemente aggiungere dinamicamente la fatidica istruzione TestoOrig = seguita da quel che occorre.

Per farla breve ecco il primo pezzo della ricetta:

Sub SvelaDocum()

  Dim TestoOrig As String ' Qui sotto verrà inserito TestoOrig = ...

  If InputBox("Password?", "Per decrittare") <> "trentatre" Then

    On Error Resume Next

    Application.DisplayAlerts = wdAlertsNone

    Me.Close

    Exit Sub

  End If

  Dim TuttiCar As Characters

  Set TuttiCar = ThisDocument.Characters

  Dim CodCar As String, i As Long

  Dim j As Long ' Indice carattere di TestoOrig

  Selection.HomeKey unit:=wdStory

  For i = 1 To TuttiCar.Count

    CodCar = Asc(Selection)

    If CodCar = 34 Or CodCar < 32 Then

      Selection.MoveRight unit:=wdCharacter, Count:=1

    Else

      Selection.MoveRight unit:=wdCharacter, Count:=1, Extend:=wdExtend

      j = j + 1

      Selection.TypeText Mid(TestoOrig, j, 1)

    End If

  Next

End Sub

 

Attenzione! È fondamentale che la riga Sub SvelaDocum sia la prima del modulo corrente. In prima battuta tale procedurina è priva della terza riga.

Ed ecco come si presenta la routine CreaStringaDoc rivisitata:

Sub CreaStringaDoc()

  Dim StringaDoc As String

  Dim TuttiCar As Characters

  Set TuttiCar = ThisDocument.Characters

  Dim car As String

  For i = 1 To TuttiCar.Count

    car = TuttiCar(i)

    If Asc(car) <> 34 Then ' Escludi le virgolette

      If Asc(car) >= 32 Then

        StringaDoc = StringaDoc & car

      End If

    End If

  Next

  ' Inserimento TestoOrig = ... in SvelaDocum

  Dim modAttivo As VBIDE.CodeModule

  Set modAttivo = Application.VBE.ActiveCodePane.CodeModule

  modAttivo.InsertLines 3, "TestoOrig = " & Chr(34) & StringaDoc & """"

End Sub

Dal confronto con la versione precedente si noterà che manca la conclusione che parcheggia il fatale TestoOrig in un nuovo Documento1. Al suo posto le istruzioni grassettate impostano un oggetto VBIDE.CodeModule a sua volta figlio dello ActiveCodePane nella variabile modAttivo resa uguale a
Application.VBE.ActiveCodePane.CodeModule

L’istruzione finale inserisce nella terza riga del modulo corrente quel che si deve. Scopritelo da soli, gente! Quel che conta è che constaterete che l’incipit della prima routine si presenterà come segue:

Sub SvelaDocum()

  Dim TestoOrig As String ' Qui sotto verrà inserito TestoOrig = ...

TestoOrig = "

  If InputBox("Password?", "Per decrittare") <> "trentatre" Then

DocSegr = "AMBArABàCicci    CoccòTre civettesul comò"

Conclusione

Come i più precisi diranno anche quest’ultimissima pur brillante soluzione non è del tutto esente da possibili malintesi. Così come l’ho presentata richiede un utente esperto e consapevole che sappia quando è il momento di lanciare le varie routine. Una versione più marcatamente a prova d’idiota al momento la lascio all’abilità e pazienza di chiunque sia interessato.

Che magari potrebbe direttamente segnalarmela:

giannigiac@tin.it

Print | posted on lunedì 26 novembre 2012 18:15 |

Feedback

No comments posted yet.

Post Comment

Title  
Name  
Email
Url
Comment   
Please add 3 and 7 and type the answer here:

Powered by:
Powered By Subtext Powered By ASP.NET