There are four concerns here:
- Pad generation
- Pad transmission
- Message privacy
- Message authenticity
The security of the one-time pad depends on the assumption that the pads are generated from a truly random source.
This is actually quite a big ask. Suppose for a moment that you want to exchange a 4 gigabyte pad. Let's say your RNG does that one byte at a time. What you're basically asking is for billions of iterations of the RNG without any kind of generation failure.
Worse, the RNG can fail in a way that is not immediately obvious or detectable. The Debian bug springs to mind here.
Or, more directly, a nation state could deliberately weaken your RNG.
The next problem is finding a secure way to transfer the pad. The pad will be longer than the message you wish to transmit, at least if you want to be able to detect alterations to your message. See below.
This immediately raises the question of what one hopes to gain by using the OTP. If you have a secure channel capable of transmitting a pad longer than the original message, why not just use this channel to transmit the message?
Given this logic, there is only really one use for the OTP, which is to time-shift a secure channel. For example, I might be able to meet my friend in the pub and give him a terabyte of pad but afterwards he might be abroad for two years.
Assuming you've solved the problems of generation and transmission, next comes actually encrypting your message. This is the most straightforward piece of the whole exercise.
You just work through your message a word at a time and logically XOR that word with a corresponding one from the pad. No part of the pad may be re-used under any circumstances. It's best to have your program destroy the read section of the pad after completing the encryption operation.
Decryption on the other end is exactly the same process. Simply logically XOR the cipher-text with the pad to recover the plain-text. This works because XOR is its own inverse:
A XOR B XOR B = A
One of the things that trips up amateurs is that encrypting your data doesn't means that nobody can undetectably alter the message in transit.
Suppose that an ATM used the OTP to encrypt its communications but no authentication. I have £0 in my bank account but I ask the ATM to give me £500. The bank replies with a single bit message which indicates whether the withdrawal is authorised or not: 1 for yes, 0 for no.
I know the bank is going to decline me so at precisely the right moment, I flip the bit before it gets to the machine. The machine spits out the £500.
You get around this problem by having a message authentication code (MAC). This is an authentication code you tack on the end of the message which acts as a secure checksum.
If I tried to flip the bit on a message with a MAC protecting it, the checksum would not longer verify and the system would know something funny is going on.
To authenticate OTP messages, you probably want to use a universal hash. This allows you to retain the security proof on both the hash and the cipher-text.
Universal hashes are a whole series of questions and answer in their own right so I'm just going to say that you should read around the subject.
The OTP is one of these ciphers that lot of amateurs gravitate towards because it's "perfectly" secure.
However, in reality we don't deal with perfection. We often don't have a secure channel with which to communicate a pad. We often don't have an RNG that has a failure rate of fractions of a billion or trillion. There are often cockups that result in pad being re-used.
For all of these reasons, competent cryptographers never recommend an OTP.