Server on a business card

It all started about 10 years ago, when I first came across article where it was described as expert on 3D technologies included a highly obstructed code ray tracer in C++ to the size of your business card.

Attention to the code - it is fully working!

Attention to the code – it is fully working!

Here's the code:

 #include <stdlib.h>   // card > aek.ppm
   #include <stdio.h>
   #include <math.h>
   typedef int i;typedef float f;struct v{
   f x,y,z;v operator+(v r){return v(x+r.x
   ,y+r.y,z+r.z);}v operator*(f r){ return
   v(x*r,y*r,z*r);}f operator%(v r){return
   x*r.x+y*r.y+z*r.z;}v(){}v operator^(v r
   ){return v(y*r.z-z*r.y,z*r.x-x*r.z,x*r.
   y-y*r.x);}v(f a,f b,f c){x=a;y=b;z=c;}v
   operator!(){return*this*(1/sqrt(*this%*
   this));}};i G[]={133022, 133266,133266,
   133022, 254096, 131216, 131984, 131072,
   258048,};f R(){return(f)rand()/RAND_MAX
   ;}i T(v o,v d,f&t,v&n){t=1e9;i m=0;f p=
   -o.z/d.z; if(.01<p)t=p, n=v(0,0,1),m=1;
   for(i k=19;k--;)for(i j=9;j--;)if(G[j]&
   1<<k){v p=o+v(-k,0,-j-4);f b=p%d,c=p%p-
   1,q=b*b-c;if(q>0){f s=-b-sqrt(q);if(s<t
   &&s>.01)t=s,n=!(p+d*t),m=2;}}return m;}
   v S(v o,v d){f t;v n;i m=T(o,d,t,n);if(
   !m)return v(.7,.6,1)*pow(1-d.z,4);v h=o
   +d*t,l=!(v(9+R(),9+R(),16)+h*-1),r=d+n*
   (n%d*-2);f b=l%n;if(b<0||T(h,l,t,n))b=0
   ;f p=pow(l%r*(b>0),99);if(m&1){h=h*.2;
   return((i)(ceil(h.x)+ceil(h.y))&1?v(3,1
   ,1):v(3,3,3))*(b*.2+.1);}return v(p,p,p
   )+S(h,r)*.5;}i main(){printf("P6 512  "
   "512 255 ");v g=!v(-6,-16,0),a=!(v(0,0,
   1)^g)*.002,b=!(g^a)*.002,c=(a+b)*-256+g
   ;for(i y=512;y--;)for(i x=512;x--;){v p
   (9,9,9);for(i r=64;r--;){v t=a*(R()-.5)
   *99+b*(R()-.5)*99;p=S(v(17,16,8)+t,!(t*
   -1+(a*(R()+x)+b*(y+R())+c)*16))*3.5+p;}
   printf("%c%c%c",(i)p.x,(i)p.y,(i)p.z);}}

After compilation:

 c++ -O3 -o card card.cpp

The author generated this picture:

I also wanted something like that, but since I still work more on servers than 3D graphics and Java, not C++, I decided that it would be cool to put business cards on the side the simplest HTTP server in Java.

Along with launch and compilation.

Even if there is a graphical environment, the browser will be launched.

Plus a little cryptography to protect against counterfeiting.

All code fit in 18 linesaligned in width to fit into the dimensions of the business card:

Enter the code from the business card into your favorite editor, save the file as vcard.sh and run:

chmod +x ./vcard.sh
./vcard.sh

Result:

FreeBSD 14 and Java 17

FreeBSD 14 and Java 17

Solaris (OpenNexenta) and JDK 22

Solaris (OpenNexenta) and JDK 22

Ubuntu and Java 1.8

Ubuntu and Java 1.8

A simple web server will start locally, which will serve a text page with text and contacts. If there is a GUI, the default browser will also launch, automatically opening the page of this server.

And all this in 18 lines of code.

Yes, you will also need any Linux/BSD/MacOS/Solaris and any version of the JDK starting from 1.8 on the machine.

I did not support launching on Windows (although this is technically possible), but you can safely run in WSL .

So that you don't have to worry about entering the code from the picture, here is the text version:

#!/bin/sh
t=$(mktemp -d);e=$(realpath  $0);sed '1,4d' $0|sed -e 's/p /public /g ; s/i /import /g' \
 -e 's/j\./java./g ; s/E!/Exception/g ; s/U8!/UTF-8/g ; s/RE?/ResponseHeaders/g'>$t/Yo.java
cd $t;javac -XDignore.symbol.file -cp . Yo.java && java -cp . Yo $e;exit 0
i com.sun.net.httpserver.*;i j.awt.Desktop;i j.io.*;i j.util.*;i j.net.*;i j.nio.file.*;
i java.security.MessageDigest;i javax.crypto.Cipher;i javax.crypto.spec.SecretKeySpec;
p class Yo{p static void main(String[]args)throws E!{Cipher dcipher=Cipher.getInstance("AES");
dcipher.init(2,new SecretKeySpec(Arrays.copyOf(MessageDigest.getInstance("SHA-1").digest(
new String(Files.readAllBytes(Paths.get(args[0]))).replaceFirst("ED=\"([^<]*)\";","")
.trim().getBytes()),16),"AES"));String ddata=new String(dcipher.doFinal(Base64.getDecoder()
.decode(ED)),"U8!");int p=8000;String h="0x7f000001";HttpServer s=HttpServer.create()
.createContext("/",(HttpExchange t)->{String r=String.format(ddata,System.nanoTime());t.getRE?()
.set("Content-type","text/plain;charset=U8!");t.sendRE?(200,r.getBytes("U8!").length);
try(OutputStream os=t.getResponseBody()){os.write(r.getBytes("U8!"));}}).getServer();
s.bind(new InetSocketAddress(p),1);new Timer().schedule(new TimerTask(){public void run(){
if(!Desktop.isDesktopSupported()){System.out.println(ddata);return;}try{Desktop.getDesktop()
.browse(new URI("http://"+h+":"+p));}catch(E! e){throw new RuntimeE!(e);}}},2000);s.start();}
static String ED="TfPrCIlXEUInGJPpr4++hQfa2Whq4RFzdbFP5C4s/s8=";}

Well, isn't it lovely?

How it works

It uses a combination of a header shell script and slightly obfuscated Java code. I also did not encode the entire block in Java completely into a HEX string, so that visually the feeling of the source code would remain.

Let's start with the header script:

#!/bin/sh
t=$(mktemp -d);e=$(realpath  $0);sed '1,4d' $0|sed -e 's/p /public /g ; s/i /import /g' \
 -e 's/j\./java./g ; s/E!/Exception/g ; s/U8!/UTF-8/g ; s/RE?/ResponseHeaders/g'>$t/Yo.java
cd $t;javac -XDignore.symbol.file -cp . Yo.java && java -cp . Yo $e;exit 0

The very first line:

#!/bin/sh

This shebanga standard Unix indication of the interpreter being used; everyone already knows about it.

Next, a temporary directory is created in /tmp and its name is assigned to a variable in the script:

t=$(mktemp -d);

Then the script gets its own name with the full path:

e=$(realpath  $0);

The script reads itself, cutting off the first 4 lines – to get a block of Java code:

sed '1,4d' $0

Next begins pipein which the result of the previous command is passed to the input of the next one:

|sed -e 's/p /public /g ; s/i /import /g' \
-e 's/j./java./g ; s/E!/Exception/g ; s/U8!/UTF-8/g ; s/RE?/ResponseHeaders/g'>а результат всех преобразований записывается в файл Yo.java, в том самом временном каталоге.Вся эта длинная и сложная сопля аргументов к sed производит «деобфрускацию» Java-кода и его восстановление в полную версию, пригодную для компиляции.Переход во временный каталог:cd " class="formula inline">t;Компиляция:javac -XDignore.symbol.file -cp . Yo.java

Little known option -XDignore.symbol.file disables the warning about the use of JDK system classes (com.sun.net.httpserver.*) in the project – in version 1.8, the classes of the HTTP server built into the JDK were still considered system classes.

Run with the full path of the original script for subsequent reading from Java code:

java -cp . Yo $e

The code itself, after de-obscuring and formatting, looks like this:

import com.sun.net.httpserver.*;
import java.awt.Desktop;
import java.io.*;
import java.util.*;
import java.net.*;
import java.nio.file.*;
import java.security.MessageDigest;
import javax.crypto.Cipher;
import javax.crypto.spec.SecretKeySpec;
public class Yo {
    public static void main(String[] args) throws Exception {
        Cipher dcipher = Cipher.getInstance("AES");
        dcipher.init(2, 
        new SecretKeySpec(Arrays.copyOf(
        MessageDigest.getInstance("SHA-1").digest(
                new String(Files.readAllBytes(Paths.get(args[0])))
                .replaceFirst("ED=\"([^<]*)\";", "")
                        .trim().getBytes()), 16), "AES"));
        String ddata = new String(dcipher.doFinal(Base64.getDecoder()
                .decode(ED)), "UTF-8");
        int p = 8000;
        String h = "0x7f000001";
        HttpServer s = HttpServer.create()
                .createContext("/", (HttpExchange t) -> {
                    String r = String.format(ddata, System.nanoTime());
                    t.getResponseHeaders()
                            .set("Content-type", "text/plain;charset=UTF-8");
                    t.sendResponseHeaders(200, r.getBytes("UTF-8").length);
                    try (OutputStream os = t.getResponseBody()) {
                        os.write(r.getBytes("UTF-8"));
                    }
                }).getServer();
        s.bind(new InetSocketAddress(p), 1);
        new Timer().schedule(new TimerTask() {
            public void run() {
                if (!Desktop.isDesktopSupported()) {
                    System.out.println(ddata);
                    return;
                }
                try {
                    Desktop.getDesktop()
                            .browse(new URI("http://" + h + ":" + p));
                } catch (Exception e) {
                    throw new RuntimeException(e);
                }
            }
        }, 2000);
        s.start();
    }
    static String ED = "1AtzGU0uq7J7DHPdjdJJ5JJDiwQi8mElIDOjuRK0DEU=";
}

Most of the logic here is already quite obvious, so I will reveal only the two most complex fragments.

Cryptography

When I first started thinking about implementing this thing, it was already clear that some kind of non-obvious integrity control was needed:

the source code will obviously be sent via messages, in the form of posts or by mail, which will easily break it.

Therefore, I wanted at least some kind of protection against content tampering, so that computer children would not add Brahmin patch to the most interesting place, and the Indian guy did not replace the authorship and my contacts with his own, for the sake of a line on his resume.

The task was complicated by the fact that open source was being transferred and the size limitation, but apparently it worked out:

 static String ED = "1AtzGU0uq7J7DHPdjdJJ5JJDiwQi8mElIDOjuRK0DEU=";

This is where the text is:

We write software. @alex0x08

For every attempt to somehow replace the content (including the header), the following error will be displayed:

Exception in thread "main" javax.crypto.BadPaddingException: Given final block not properly padded. Such issues can arise if a bad key is used during decryption.
	at java.base/com.sun.crypto.provider.CipherCore.unpad(CipherCore.java:981)
	at java.base/com.sun.crypto.provider.CipherCore.fillOutputBuffer(CipherCore.java:1062)
	at java.base/com.sun.crypto.provider.CipherCore.doFinal(CipherCore.java:853)
	at java.base/com.sun.crypto.provider.AESCipher.engineDoFinal(AESCipher.java:446)
	at java.base/javax.crypto.Cipher.doFinal(Cipher.java:2202)
	at Yo.main(Yo.java:6)

It turns out that the code protects itself from tampering.

0x7f000001

The second non-obvious point is this strange host address:

 String h = "0x7f000001";

which is used when generating a link to be opened by a browser:

Desktop.getDesktop().browse(new URI("http://" + h + ":" + p));

This use clearly indicates that the address is very standard, since it goes through both a validation stage on the Java side when forming a URI object, and validation on the side of the launched browser.

In general, this is just a notation, a variant of the spelling of the IP address 127.0.0.1, indicating loopback (loopback) – an internal interface that can be connected to locally, rather than from the network.

Here here More examples of different spellings of IP addresses, I’m sure, will surprise even experienced admins.

The more frivolous original article is at our blogwhere we talk in detail about the horrors of development, driving even the experienced and seasoned into blush.

0x08 Software

We are a small team of IT industry veterans, we create and develop a wide variety of software; our software automates business processes on three continents, in a wide variety of industries and conditions.

Let's revive long dead, fixing something that never worked and create impossible – then we talk about it in our articles.

Similar Posts

Leave a Reply

Your email address will not be published. Required fields are marked *