Main step of GOST 28147-89: Difference between revisions

m
(Added Perl 6 code.)
 
(71 intermediate revisions by 25 users not shown)
Line 1:
{{task|Encryption}}
[[wp:GOST (block cipher)|GOST 28147-89]] is a standard symmetric encryption based on a [[wp:Feistel cipher|Feistel network]]. Structure of the algorithm consists of three levels:
 
[https://tools.ietf.org/html/rfc5830 GOST 28147-89] is a standard symmetric encryption based on a [http://cryptowiki.net/index.php?title=Generalized_Feistel_networks Feistel network].
# encryption modes - simple replacement, application range, imposing a range of feedback and authentication code generation;
# cycles - 32-З, 32-Р and 16-З, is a repetition of the main step;
# ''main step'', a function that takes a 64-bit block of text and one of the eight 32-bit encryption key elements, and uses the replacement table (8x16 matrix of 4-bit values), and returns encrypted block.
 
 
The structure of the algorithm consists of three levels:
#   encryption modes - simple replacement, application range, imposing a range of feedback and authentication code generation;
#   cycles - 32-З, 32-Р and 16-З, is a repetition of the main step;
#   ''main step'', a function that takes a 64-bit block of text and one of the eight 32-bit encryption key elements, and uses the replacement table (8x16 matrix of 4-bit values), and returns encrypted block.
 
 
;Task:
Implement the main step of this encryption algorithm.
<br><br>
 
=={{header|BBC BASIC}}==
{{works with|BBC BASIC for Windows}}
<syntaxhighlight lang="bbcbasic"> DIM table&(7,15), test%(1)
table&() = 4, 10, 9, 2, 13, 8, 0, 14, 6, 11, 1, 12, 7, 15, 5, 3, \
\ 14, 11, 4, 12, 6, 13, 15, 10, 2, 3, 8, 1, 0, 7, 5, 9, \
\ 5, 8, 1, 13, 10, 3, 4, 2, 14, 15, 12, 7, 6, 0, 9, 11, \
\ 7, 13, 10, 1, 0, 8, 9, 15, 14, 4, 6, 12, 11, 2, 5, 3, \
\ 6, 12, 7, 1, 5, 15, 13, 8, 4, 10, 9, 14, 0, 3, 11, 2, \
\ 4, 11, 10, 0, 7, 2, 1, 13, 3, 6, 8, 5, 9, 12, 15, 14, \
\ 13, 11, 4, 1, 3, 15, 5, 9, 0, 10, 14, 7, 6, 8, 2, 12, \
\ 1, 15, 13, 0, 5, 7, 10, 4, 9, 2, 3, 14, 6, 11, 8, 12
test%() = &043B0421, &04320430
key% = &E2C104F9
PROCmainstep(test%(), key%, table&())
PRINT ~ test%(0) test%(1)
END
DEF PROCmainstep(n%(), key%, t&())
LOCAL i%, s%, cell&, new_s%
s% = FN32(n%(0) + key%)
FOR i% = 0 TO 3
cell& = (s% >>> (i%*8)) AND &FF
new_s% += (t&(i%*2,cell& MOD 16) + 16*t&(i%*2+1,cell& DIV 16)) << (i%*8)
NEXT
s% = ((new_s% << 11) OR (new_s% >>> 21)) EOR n%(1)
n%(1) = n%(0) : n%(0) = s%
ENDPROC
DEF FN32(v)
WHILE v>&7FFFFFFF : v-=2^32 : ENDWHILE
WHILE v<&80000000 : v+=2^32 : ENDWHILE
= v</syntaxhighlight>
'''Output:'''
<pre>
7CF881F 43B0421
</pre>
 
=={{header|C}}==
Version with packed replacement table.
 
<langsyntaxhighlight Clang="c">static unsigned char k87const k8[25616] = { 14, 4, 13, 1, 2, 15, 11, 8, 3, 10, 6, 12, 5, 9, 0, 7 };
static unsigned char const k7[16] = { 15, 1, 8, 14, 6, 11, 3, 4, 9, 7, 2, 13, 12, 0, 5, 10 };
static unsigned char const k6[16] = { 10, 0, 9, 14, 6, 3, 15, 5, 1, 13, 12, 7, 11, 4, 2, 8 };
static unsigned char const k5[16] = { 7, 13, 14, 3, 0, 6, 9, 10, 1, 2, 8, 5, 11, 12, 4, 15 };
static unsigned char const k4[16] = { 2, 12, 4, 1, 7, 10, 11, 6, 8, 5, 3, 15, 13, 0, 14, 9 };
static unsigned char const k3[16] = { 12, 1, 10, 15, 9, 2, 6, 8, 0, 13, 3, 4, 14, 7, 5, 11 };
static unsigned char const k2[16] = { 4, 11, 2, 14, 15, 0, 8, 13, 3, 12, 9, 7, 5, 10, 6, 1 };
static unsigned char const k1[16] = { 13, 2, 8, 4, 6, 15, 11, 1, 10, 9, 3, 14, 5, 0, 12, 7 };
 
static unsigned char k87[256];
static unsigned char k65[256];
static unsigned char k43[256];
Line 34 ⟶ 87:
k43[x>> 8 & 255] << 8 | k21[x & 255];
return x<<11 | x>>(32-11);
}</langsyntaxhighlight>
 
=={{header|C++#}}==
{{trans|Go}}
<syntaxhighlight lang="C#">
using System;
 
class Gost
<lang Cpp>UINT_32 TGost::ROL(UINT_32 X, BYTE n)
{
private byte[,] sBox = new byte[8, 16];
_asm{
private byte[] k87 = new byte[256];
mov eax, X
private movbyte[] k65 cl,= new nbyte[256];
private byte[] k43 = new byte[256];
rol eax, cl
private byte[] k21 = new byte[256];
mov X,eax
private byte[] enc = new byte[8];
 
public Gost(byte[,] s)
{
sBox = s;
for (int i = 0; i < 256; i++)
{
k87[i] = (byte)((sBox[7, i >> 4] << 4) | sBox[6, i & 15]);
k65[i] = (byte)((sBox[5, i >> 4] << 4) | sBox[4, i & 15]);
k43[i] = (byte)((sBox[3, i >> 4] << 4) | sBox[2, i & 15]);
k21[i] = (byte)((sBox[1, i >> 4] << 4) | sBox[0, i & 15]);
}
}
 
private uint F(uint x)
return UINT_32(X);
{
x = (uint)(k87[x >> 24 & 255] << 24) | (uint)(k65[x >> 16 & 255] << 16) |
(uint)(k43[x >> 8 & 255] << 8) | (uint)(k21[x & 255]);
return x << 11 | x >> (32 - 11);
}
 
private static uint U32(byte[] b)
{
return (uint)(b[0] | b[1] << 8 | b[2] << 16 | b[3] << 24);
}
 
private static void B4(uint u, byte[] b)
{
b[0] = (byte)u;
b[1] = (byte)(u >> 8);
b[2] = (byte)(u >> 16);
b[3] = (byte)(u >> 24);
}
 
public void MainStep(byte[] input, byte[] key)
{
uint key32 = U32(key);
uint input1 = U32(input, 0);
uint input2 = U32(input, 4);
B4(F(key32 + input1) ^ input2, enc, 0);
Array.Copy(input, 0, enc, 4, 4);
}
 
public byte[] Enc => enc;
 
private static uint U32(byte[] b, int index)
{
return (uint)(b[index] | b[index + 1] << 8 | b[index + 2] << 16 | b[index + 3] << 24);
}
 
private static void B4(uint u, byte[] b, int index)
{
b[index] = (byte)u;
b[index + 1] = (byte)(u >> 8);
b[index + 2] = (byte)(u >> 16);
b[index + 3] = (byte)(u >> 24);
}
}
 
class Program
UINT_64 TGost::SWAP32(UINT_32 N1, UINT_32 N2)
{
static void Main(string[] args)
{
byte[,] cbrf = {
{4, 10, 9, 2, 13, 8, 0, 14, 6, 11, 1, 12, 7, 15, 5, 3},
{14, 11, 4, 12, 6, 13, 15, 10, 2, 3, 8, 1, 0, 7, 5, 9},
{5, 8, 1, 13, 10, 3, 4, 2, 14, 15, 12, 7, 6, 0, 9, 11},
{7, 13, 10, 1, 0, 8, 9, 15, 14, 4, 6, 12, 11, 2, 5, 3},
{6, 12, 7, 1, 5, 15, 13, 8, 4, 10, 9, 14, 0, 3, 11, 2},
{4, 11, 10, 0, 7, 2, 1, 13, 3, 6, 8, 5, 9, 12, 15, 14},
{13, 11, 4, 1, 3, 15, 5, 9, 0, 10, 14, 7, 6, 8, 2, 12},
{1, 15, 13, 0, 5, 7, 10, 4, 9, 2, 3, 14, 6, 11, 8, 12},
};
 
byte[] input = { 0x21, 0x04, 0x3B, 0x04, 0x30, 0x04, 0x32, 0x04 };
byte[] key = { 0xF9, 0x04, 0xC1, 0xE2 };
 
Gost g = new Gost(cbrf);
g.MainStep(input, key);
 
foreach (var b in g.Enc)
{
Console.Write("[{0:x2}]", b);
}
Console.WriteLine();
}
}
</syntaxhighlight>
{{out}}
<pre>
[1f][88][cf][07][21][04][3b][04]
 
</pre>
 
=={{header|C++}}==
<syntaxhighlight lang="cpp">UINT_64 TGost::SWAP32(UINT_32 N1, UINT_32 N2)
{
UINT_64 N;
Line 78 ⟶ 224:
S = N1 + X % 0x4000000000000;
S = ReplaceBlock(S);
S = ROL(S,<<11)|(S>>21);
_asm{S ^= N2;
mov eax,N2
xor S,eax
}
N2 = N1;
N1 = S;
return SWAP32(N2,N1);
}</langsyntaxhighlight>
 
Variable "BS" is the replacement table.
 
=={{header|JavaScriptD}}==
{{trans|C}}
<lang JavaScript>function ОсновнойШаг(блок_текста, элемент_ключа) {
{{trans|Go}}
var N = блок_текста.slice(0);
<syntaxhighlight lang="d">import std.stdio, std.range, std.algorithm;
var X = элемент_ключа;
 
var S = (N[0] + X) & 0xFFFFFFFF;
/// Rotate uint left.
var ячейка; var нов_S = 0;
uint rol(in uint x, in uint nBits) @safe pure nothrow @nogc {
for (var сч = 0; сч < 4; сч++) {
ячейкаreturn =(x << nBits) | (Sx >>> (сч32 <<- 3nBits)) & 0xFF;
}
нов_S += (ТаблицаЗамен[сч*2][ячейка & 0x0F] + (ТаблицаЗамен[сч*2+1][ячейка >>> 4] << 4)) << (сч << 3);
 
}
alias Nibble = ubyte; // 4 bits used.
S = (((нов_S << 11) + (нов_S >>> 21)) & 0xFFFFFFFF) ^ N[1];
alias SBox = immutable Nibble[16][8];
N[1] = N[0]; N[0] = S;
 
return N;
private bool _validateSBox(in SBox data) @safe pure nothrow @nogc {
}</lang>
foreach (const ref row; data)
foreach (ub; row)
if (ub >= 16) // Verify it's a nibble.
return false;
return true;
}
 
struct GOST(s...) if (s.length == 1 && s[0]._validateSBox) {
private static generate(ubyte k)() @safe pure nothrow {
return k87.length.iota
.map!(i=> (s[0][k][i >> 4] << 4) | s[0][k - 1][i & 0xF])
.array;
}
 
private uint[2] buffer;
private static immutable ubyte[256] k87 = generate!7,
k65 = generate!5,
k43 = generate!3,
k21 = generate!1;
 
// Endianess problems?
private static uint f(in uint x) pure nothrow @nogc @safe {
immutable uint y = (k87[(x >> 24) & 0xFF] << 24) |
(k65[(x >> 16) & 0xFF] << 16) |
(k43[(x >> 8) & 0xFF] << 8) |
k21[ x & 0xFF];
return rol(y, 11);
}
 
// This performs only a step of the encoding.
public void mainStep(in uint[2] input, in uint key)
pure nothrow @nogc @safe {
buffer[0] = f(key + input[0]) ^ input[1];
buffer[1] = input[0];
}
}
 
void main() {
// S-boxes used by the Central Bank of Russian Federation:
// http://en.wikipedia.org/wiki/GOST_28147-89
// (This is a matrix of nibbles).
enum SBox cbrf = [
[ 4, 10, 9, 2, 13, 8, 0, 14, 6, 11, 1, 12, 7, 15, 5, 3],
[14, 11, 4, 12, 6, 13, 15, 10, 2, 3, 8, 1, 0, 7, 5, 9],
[ 5, 8, 1, 13, 10, 3, 4, 2, 14, 15, 12, 7, 6, 0, 9, 11],
[ 7, 13, 10, 1, 0, 8, 9, 15, 14, 4, 6, 12, 11, 2, 5, 3],
[ 6, 12, 7, 1, 5, 15, 13, 8, 4, 10, 9, 14, 0, 3, 11, 2],
[ 4, 11, 10, 0, 7, 2, 1, 13, 3, 6, 8, 5, 9, 12, 15, 14],
[13, 11, 4, 1, 3, 15, 5, 9, 0, 10, 14, 7, 6, 8, 2, 12],
[ 1, 15, 13, 0, 5, 7, 10, 4, 9, 2, 3, 14, 6, 11, 8, 12]];
 
GOST!cbrf g;
 
// Example from the talk page (bytes swapped for endianess):
immutable uint[2] input = [0x_04_3B_04_21, 0x_04_32_04_30];
immutable uint key = 0x_E2_C1_04_F9;
 
g.mainStep(input, key);
writefln("%(%08X %)", g.buffer);
}</syntaxhighlight>
{{out}}
<pre>07CF881F 043B0421</pre>
 
=={{header|FreeBASIC}}==
{{trans|Python}}
<syntaxhighlight lang="freebasic">Dim Shared As Ubyte k87(255), k65(255), k43(255), k21(255)
 
Sub kboxinit()
Dim As Ubyte k8(15) = {14, 4, 13, 1, 2, 15, 11, 8, 3, 10, 6, 12, 5, 9, 0, 7}
Dim As Ubyte k7(15) = {15, 1, 8, 14, 6, 11, 3, 4, 9, 7, 2, 13, 12, 0, 5, 10}
Dim As Ubyte k6(15) = {10, 0, 9, 14, 6, 3, 15, 5, 1, 13, 12, 7, 11, 4, 2, 8}
Dim As Ubyte k5(15) = { 7, 13, 14, 3, 0, 6, 9, 10, 1, 2, 8, 5, 11, 12, 4, 15}
Dim As Ubyte k4(15) = { 2, 12, 4, 1, 7, 10, 11, 6, 8, 5, 3, 15, 13, 0, 14, 9}
Dim As Ubyte k3(15) = {12, 1, 10, 15, 9, 2, 6, 8, 0, 13, 3, 4, 14, 7, 5, 11}
Dim As Ubyte k2(15) = { 4, 11, 2, 14, 15, 0, 8, 13, 3, 12, 9, 7, 5, 10, 6, 1}
Dim As Ubyte k1(15) = {13, 2, 8, 4, 6, 15, 11, 1, 10, 9, 3, 14, 5, 0, 12, 7}
For i As Uinteger = 0 To 255
k87(i) = k8(i Shr 4) Shl 4 Or k7(i And 15)
k65(i) = k6(i Shr 4) Shl 4 Or k5(i And 15)
k43(i) = k4(i Shr 4) Shl 4 Or k3(i And 15)
k21(i) = k2(i Shr 4) Shl 4 Or k1(i And 15)
Next i
End Sub
 
Function f(x As Integer) As Integer
x = k87(x Shr 24 And 255) Shl 24 Or k65(x Shr 16 And 255) Shl 16 Or _
k43(x Shr 8 And 255) Shl 8 Or k21(x And 255)
Return x Shl 11 Or x Shr (32-11)
End Function</syntaxhighlight>
 
Note: the variable "блок_текста" is an array of two 32-bit values that make up the block.
 
=={{header|Glagol}}==
Line 168 ⟶ 400:
 
=={{header|Go}}==
<syntaxhighlight lang="go">package main
See talk page
<lang go>package main
 
import "fmt"
Line 177 ⟶ 408:
type gost struct {
k87, k65, k43, k21 [256]byte
enc []byte
}
 
Line 187 ⟶ 419:
g.k21[i] = s[1][i>>4]<<4 | s[0][i&15]
}
g.enc = make([]byte, 8)
return &g
}
Line 198 ⟶ 431:
// code above adapted from posted C code
 
// validation code below is verification attempt, followingfollows example on talk page
 
// cbrf from WP
var cbrf = sBox{
{4, 10, 9, 2, 13, 8, 0, 14, 6, 11, 1, 12, 7, 15, 5, 3},
Line 223 ⟶ 456:
}
 
func (g *gost) mainStep(input []byte, key []byte) {
func main() {
input := []byte{0x21, 0x04, 0x3B, 0x04, 0x30, 0x04, 0x32, 0x04}
key := []byte{0xF9, 0x04, 0xC1, 0xE2}
 
key32 := u32(key)
input1 := u32(input[:4])
input2 := u32(input[4:])
b4(g.f(key32+input1)^input2, g.enc[:4])
copy(g.enc[4:], input[:4])
}
 
func main() {
input := []byte{0x21, 0x04, 0x3B, 0x04, 0x30, 0x04, 0x32, 0x04}
key := []byte{0xF9, 0x04, 0xC1, 0xE2}
 
g := newGost(&cbrf)
enc := makeg.mainStep([]byteinput, 8key)
for _, b := range g.enc {
b4(g.f(key32+input1)^input2, enc[:4])
b4(g.f(key32+input2)^input1, enc[4:])
for _, b := range enc {
fmt.Printf("[%02x]", b)
}
fmt.Println()
}</langsyntaxhighlight>
{{out}}
<pre>
[1f][88][cf][07][0e21][5804][c13b][0f04]
</pre>
 
=={{header|Java}}==
<syntaxhighlight lang="java">
import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.List;
import java.util.function.IntUnaryOperator;
import java.util.stream.Collectors;
import java.util.stream.IntStream;
 
/**
=={{header|Perl 6}}==
* Encrypt and decrypt messages in unicode characters using the GOST 28147-89 (Magma) algorithm.
*
* For further information visit https://en.wikipedia.org/wiki/GOST_(block_cipher)
*/
public final class MainStepGOST28147_89 {
 
public static void main(String[] aArgs) {
Implemented to match explanation on Discussion page:
// Initialisation
String plainText = "The spy 我 lives in Iž";
GOST28147_89 gost = new GOST28147_89(plainText);
// Display the plain text and the plain text bytes
System.out.println("The plain text is: \"" + plainText + "\"" + System.lineSeparator());
String plainTextBinary = gost.getPlainTextBinary();
displayBytesFromBinary("The plain text bytes are: ", plainTextBinary);
// Encryption
String encryptedBinary = gost.gostAlgorithm(plainTextBinary, Cryptation.ENCRYPT);
// Display the encrypted text bytes and the encrypted text
List<Character> encryptedChars = displayBytesFromBinary("The encrypted text bytes are: ", encryptedBinary);
String encryptedText = encryptedChars.stream().map(String::valueOf).collect(Collectors.joining());
System.out.println("The encrypted text is: \"" + encryptedText + "\"" + System.lineSeparator());
// Decryption
String decryptedBinary = gost.gostAlgorithm(encryptedBinary, Cryptation.DECRYPT);
// Display the decrypted text bytes and the decrypted text
List<Character> decryptedChars = displayBytesFromBinary("The decrypted text bytes are: ", decryptedBinary);
byte[] bytes = new byte[decryptedChars.size()];
IntStream.range(0, decryptedChars.size()).forEach( i -> bytes[i] = (byte) decryptedChars.get(i).charValue() );
System.out.println("The decrypted text is: \"" + new String(bytes) + "\"" + System.lineSeparator());
}
/**
* Display the given tile string together with a list of bytes obtained from the given binary string.
* Return a list of characters obtained from the given binary string.
*/
private static List<Character> displayBytesFromBinary(String aTitle, String aBinaryBlock) {
List<Character> chars = new ArrayList<Character>();
List<String> bytes = new ArrayList<String>();
for ( int i = 0; i < aBinaryBlock.length(); i += 8 ) {
char ch = (char) Integer.parseInt(aBinaryBlock.substring(i, i + 8), 2);
chars.add(ch);
bytes.add(String.format("%2s", Integer.toHexString(ch)).replace(" ", "0"));
}
System.out.println(aTitle);
for ( int i = 0; i < bytes.size(); i += 8 ) {
System.out.print(bytes.subList(i, i + 8));
}
System.out.println(System.lineSeparator());
return chars;
}
}
 
enum Cryptation { ENCRYPT, DECRYPT }
 
final class GOST28147_89 {
public GOST28147_89(String aPlainText) {
createSbox();
createKeys();
plainTextBinary = convertCharactersToBinary(aPlainText, StandardCharsets.UTF_8);
}
/**
* Encrypt or decrypt the given binary string according to the value of the given enum,
* using the GOST 28147-89 (Magma) algorithm.
*/
public String gostAlgorithm(String aBinaryBlock, Cryptation aCryptation) {
StringBuilder stringBuilder = new StringBuilder();
for ( int i = 0; i < aBinaryBlock.length(); i += 64 ) {
String one = reverse(aBinaryBlock.substring(i, i + 32));
String two = reverse(aBinaryBlock.substring(i + 32, i + 64));
List<String> pair;
switch ( aCryptation ) {
case ENCRYPT -> { pair = mainStep(one, two, 24, k -> k % 8);
pair = mainStep(pair.get(0), pair.get(1), 8, k -> 7 - k);
stringBuilder.append(reverse(pair.get(0)));
stringBuilder.append(reverse(pair.get(1)));
}
case DECRYPT -> { pair = mainStep(two, one, 8, k -> k);
pair = mainStep(pair.get(0), pair.get(1), 24, k -> 7 - k % 8);
stringBuilder.append(reverse(pair.get(1)));
stringBuilder.append(reverse(pair.get(0)));
}
};
}
return stringBuilder.toString();
}
public String getPlainTextBinary() {
return plainTextBinary;
}
// PRIVATE //
 
/**
* Perform the main step of the GOST 28147-89 (Magma) algorithm.
*/
private List<String> mainStep(String aLeft, String aRight, int aIterations, IntUnaryOperator aOperator) {
for ( int i = 0; i < aIterations; i++ ) {
long sum = Long.parseLong(aRight, 2) + Integer.parseInt(keys.get(aOperator.applyAsInt(i)), 2);
sum %= Math.pow(2, 32);
String newSum = String.format("%32s", Long.toBinaryString(sum)).replace(" ", "0");
newSum = shiftLeft(sBoxFunction(newSum));
String temp = aLeft;
aLeft = aRight;
long xor = Long.parseLong(newSum, 2) ^ Long.parseLong(temp, 2);
aRight = String.format("%32s", Long.toBinaryString(xor)).replace(" ", "0");
}
return List.of(aLeft, aRight);
}
/**
* Convert each byte in the given string to its ASCII code value as a binary number,
* and concatenate these binary numbers into a single string.
* Pad the resulting string so that its length is a multiple of 8 bytes which is 64 bits.
*/
private String convertCharactersToBinary(String aBytes, Charset aCharset) {
StringBuilder stringBuilder = new StringBuilder();
for ( byte bbyte : aBytes.getBytes(aCharset) ) {
String binary = String.format("%8s", Integer.toBinaryString(bbyte & 0xff)).replace(" ", "0");
stringBuilder.append(binary);
}
String binaryBlock = stringBuilder.toString();
while ( binaryBlock.length() % 64 > 0 ) {
binaryBlock += "00100000"; // The ASCII code for the space character as a binary number.
}
return binaryBlock;
}
/**
* Left shift the given string by 11 bits.
*/
private String shiftLeft(String aBinaryBlock) {
return aBinaryBlock.substring(11) + aBinaryBlock.substring(0, 11);
}
/**
* Return the reverse of the given string.
*/
private String reverse(String aText) {
return new StringBuilder(aText).reverse().toString();
}
/**
* Convert the 32 character KEY_TEXT into a 256 bit binary string.
* Then convert this string into 8 keys each consisting of a 32 bit string.
*/
private void createKeys() {
if ( KEY_TEXT.length() != 32 ) {
throw new AssertionError("The KEY_TEXT must contain exactly 32 characters");
}
String binaryKey = convertCharactersToBinary(KEY_TEXT, StandardCharsets.UTF_8);
keys = new ArrayList<String>();
for ( int i = 0; i < 256; i += 32 ) {
keys.add( new String(binaryKey.substring(i, i + 32)) );
}
}
/**
* Split the given 32 bit string into 8 parts,
* and replace each part with its respective hexadecimal number from the sBox.
*/
private String sBoxFunction(String aBinaryBlock) {
StringBuilder result = new StringBuilder();
for ( int i = 0; i < 32; i += 4 ) {
int number = Integer.parseInt(aBinaryBlock.substring(i, i + 4), 2);
int boxNumber = Integer.parseInt(sBox.get(i / 4).substring(number, number + 1), 16);
String binary = Integer.toBinaryString(boxNumber).replace(" ", "0");
result.append(binary);
}
return result.toString();
}
/**
* Create a list of strings of hexadecimal digits.
*/
private void createSbox() {
sBox = List.of(
"4A92D80E6B1C7F53",
"EB4C6DFA23810759",
"581DA342EFC7609B",
"7DA1089FE46CB253",
"6C715FD84A9E03B2",
"4BA0721D36859CFE",
"DB413F590AE7682C",
"1FD057A4923E6B8C");
}
private List<String> sBox;
private List<String> keys;
private String plainTextBinary;
// The KEY_TEXT must contain exactly 32 characters.
private final String KEY_TEXT = "Kriptografi Metode GOST, Andysah";
}
</syntaxhighlight>
{{ out }}
<pre>
The plain text is: "The spy 我 lives in Iž"
 
The plain text bytes are:
[54, 68, 65, 20, 73, 70, 79, 20][e6, 88, 91, 20, 6c, 69, 76, 65][73, 20, 69, 6e, 20, 49, c5, be]
 
The encrypted text bytes are:
[aa, 67, e0, 72, 66, 3a, 97, 42][7b, 9f, e6, 88, f3, d0, 70, 25][27, 3f, 2c, 40, 43, 59, e0, 9e]
 
The encrypted text is: "ªgàrf:—B{ŸæˆóÐp%'?,@CYàž"
 
The decrypted text bytes are:
[54, 68, 65, 20, 73, 70, 79, 20][e6, 88, 91, 20, 6c, 69, 76, 65][73, 20, 69, 6e, 20, 49, c5, be]
 
The decrypted text is: "The spy 我 lives in Iž"
</pre>
 
=={{header|JavaScript}}==
<syntaxhighlight lang="javascript">
const Таблица_замен = [
[ 4, 10, 9, 2, 13, 8, 0, 14, 6, 11, 1, 12, 7, 15, 5, 3],
[14, 11, 4, 12, 6, 13, 15, 10, 2, 3, 8, 1, 0, 7, 5, 9],
[ 5, 8, 1, 13, 10, 3, 4, 2, 14, 15, 12, 7, 6, 0, 9, 11],
[ 7, 13, 10, 1, 0, 8, 9, 15, 14, 4, 6, 12, 11, 2, 5, 3],
[ 6, 12, 7, 1, 5, 15, 13, 8, 4, 10, 9, 14, 0, 3, 11, 2],
[ 4, 11, 10, 0, 7, 2, 1, 13, 3, 6, 8, 5, 9, 12, 15, 14],
[13, 11, 4, 1, 3, 15, 5, 9, 0, 10, 14, 7, 6, 8, 2, 12],
[ 1, 15, 13, 0, 5, 7, 10, 4, 9, 2, 3, 14, 6, 11, 8, 12]
];
 
const Основной_шаг = (блок_текста, элемент_ключа, ТЗ) => {
const
N = блок_текста.slice(0),
S = N[0] + элемент_ключа & 0xFFFFFFFF;
let нов_S = 0;
for (let сч = 0; сч < 4; сч++) {
const яч = (S >>> (сч << 3)) & 0xFF;
нов_S += ТЗ[сч * 2][яч & 0x0F] + (ТЗ[сч * 2 + 1][яч >>> 4] << 4) << (сч << 3);
}
нов_S = (нов_S << 11) + (нов_S >>> 21) & 0xFFFFFFFF ^ N[1];
N[1] = N[0]; N[0] = нов_S;
return N;
};
</syntaxhighlight>
 
Note: the variable "блок_текста" is an array of two 32-bit values that make up the block.
 
=={{header|Julia}}==
{{trans|Kotlin}}
<syntaxhighlight lang="julia">
const k8 = [ 4, 10, 9, 2, 13, 8, 0, 14, 6, 11, 1, 12, 7, 15, 5, 3]
const k7 = [14, 11, 4, 12, 6, 13, 15, 10, 2, 3, 8, 1, 0, 7, 5, 9]
const k6 = [ 5, 8, 1, 13, 10, 3, 4, 2, 14, 15, 12, 7, 6, 0, 9, 11]
const k5 = [ 7, 13, 10, 1, 0, 8, 9, 15, 14, 4, 6, 12, 11, 2, 5, 3]
const k4 = [ 6, 12, 7, 1, 5, 15, 13, 8, 4, 10, 9, 14, 0, 3, 11, 2]
const k3 = [ 4, 11, 10, 0, 7, 2, 1, 13, 3, 6, 8, 5, 9, 12, 15, 14]
const k2 = [13, 11, 4, 1, 3, 15, 5, 9, 0, 10, 14, 7, 6, 8, 2, 12]
const k1 = [ 1, 15, 13, 0, 5, 7, 10, 4, 9, 2, 3, 14, 6, 11, 8, 12]
const k87 = zeros(UInt32,256)
const k65 = zeros(UInt32,256)
const k43 = zeros(UInt32,256)
const k21 = zeros(UInt32,256)
for i in 1:256
j = (i-1) >> 4 + 1
k = (i-1) & 15 + 1
k87[i] = (k1[j] << 4) | k2[k]
k65[i] = (k3[j] << 4) | k4[k]
k43[i] = (k5[j] << 4) | k6[k]
k21[i] = (k7[j] << 4) | k8[k]
end
 
function f(x)
y = (k87[(x>>24) & 0xff + 1] << 24) | (k65[(x>>16) & 0xff + 1] << 16) |
(k43[(x>> 8) & 0xff + 1] << 8) | k21[x & 0xff + 1]
(y << 11) | (y >> (32-11))
end
 
bytes2int(arr) = reinterpret(UInt32, arr)[begin]
int2bytes(x) = reinterpret(UInt8, [x])
 
function mainstep(inputbytes, keybytes)
intkey = bytes2int(keybytes)
lowint = bytes2int(inputbytes[1:4])
topint = bytes2int(inputbytes[5:8])
xorbytes = f(UInt32(intkey) + UInt32(lowint)) ⊻ topint
vcat(int2bytes(xorbytes), inputbytes[1:4])
end
 
const input = [0x21, 0x04, 0x3B, 0x04, 0x30, 0x04, 0x32, 0x04]
const key = [0xF9, 0x04, 0xC1, 0xE2]
println("The encoded bytes are $(mainstep(input, key))")
</syntaxhighlight>
{{output}}<pre>
The encoded bytes are UInt8[0x1f, 0x88, 0xcf, 0x07, 0x21, 0x04, 0x3b, 0x04]</pre>
 
=={{header|Kotlin}}==
{{trans|Go}}
<syntaxhighlight lang="scala">// version 1.1.4-3
 
fun Byte.toUInt() = java.lang.Byte.toUnsignedInt(this)
 
fun Byte.toULong() = java.lang.Byte.toUnsignedLong(this)
 
fun Int.toULong() = java.lang.Integer.toUnsignedLong(this)
 
val s = arrayOf(
byteArrayOf( 4, 10, 9, 2, 13, 8, 0, 14, 6, 11, 1, 12, 7, 15, 5, 3),
byteArrayOf(14, 11, 4, 12, 6, 13, 15, 10, 2, 3, 8, 1, 0, 7, 5, 9),
byteArrayOf( 5, 8, 1, 13, 10, 3, 4, 2, 14, 15, 12, 7, 6, 0, 9, 11),
byteArrayOf( 7, 13, 10, 1, 0, 8, 9, 15, 14, 4, 6, 12, 11, 2, 5, 3),
byteArrayOf( 6, 12, 7, 1, 5, 15, 13, 8, 4, 10, 9, 14, 0, 3, 11, 2),
byteArrayOf( 4, 11, 10, 0, 7, 2, 1, 13, 3, 6, 8, 5, 9, 12, 15, 14),
byteArrayOf(13, 11, 4, 1, 3, 15, 5, 9, 0, 10, 14, 7, 6, 8, 2, 12),
byteArrayOf( 1, 15, 13, 0, 5, 7, 10, 4, 9, 2, 3, 14, 6, 11, 8, 12)
)
 
class Gost(val sBox: Array<ByteArray>) {
 
val k87 = ByteArray(256)
val k65 = ByteArray(256)
val k43 = ByteArray(256)
val k21 = ByteArray(256)
val enc = ByteArray(8)
 
init {
for (i in 0 until 256) {
val j = i ushr 4
val k = i and 15
k87[i] = ((sBox[7][j].toUInt() shl 4) or sBox[6][k].toUInt()).toByte()
k65[i] = ((sBox[5][j].toUInt() shl 4) or sBox[4][k].toUInt()).toByte()
k43[i] = ((sBox[3][j].toUInt() shl 4) or sBox[2][k].toUInt()).toByte()
k21[i] = ((sBox[1][j].toUInt() shl 4) or sBox[0][k].toUInt()).toByte()
}
}
 
fun f(x: Int): Int {
val y = (k87[(x ushr 24) and 255].toULong() shl 24) or
(k65[(x ushr 16) and 255].toULong() shl 16) or
(k43[(x ushr 8) and 255].toULong() shl 8) or
(k21[ x and 255].toULong())
return ((y shl 11) or (y ushr 21)).toInt()
}
 
fun u32(ba: ByteArray): Int =
(ba[0].toULong() or
(ba[1].toULong() shl 8) or
(ba[2].toULong() shl 16) or
(ba[3].toULong() shl 24)).toInt()
 
fun b4(u: Int) {
enc[0] = u.toByte()
enc[1] = (u ushr 8).toByte()
enc[2] = (u ushr 16).toByte()
enc[3] = (u ushr 24).toByte()
}
 
fun mainStep(input: ByteArray, key: ByteArray) {
val key32 = u32(key)
val input1 = u32(input.sliceArray(0..3))
val input2 = u32(input.sliceArray(4..7))
val temp = (key32.toULong() + input1.toULong()).toInt()
b4(f(temp) xor input2)
for (i in 0..3) enc[4 + i] = input[i]
}
}
 
fun main(args: Array<String>) {
val input = byteArrayOf(0x21, 0x04, 0x3B, 0x04, 0x30, 0x04, 0x32, 0x04)
val key = byteArrayOf(0xF9.toByte(), 0x04, 0xC1.toByte(), 0xE2.toByte())
val g = Gost(s)
g.mainStep(input, key)
for (b in g.enc) print("[%02X]".format(b))
println()
}</syntaxhighlight>
 
{{out}}
<pre>
[1F][88][CF][07][21][04][3B][04]
</pre>
 
=={{header|МК-61/52}}==
This program is designed to run on the two modules. This is due to the use of exclusive-or function, requiring the conversion of numbers in a particular format, and related resource consumption.
 
Code for the first module:
<syntaxhighlight lang="text">ИП6 С/П + П6 ИП7 С/П + П7 ИПE -
x>=0 14 П7 КИП6 ИП6 ИПE - x>=0 20 П6
8 П2 П3 2 П1 4 П0 0 П8 1
П9 КИП2 ИПB / [x] ПA Вх {x} ИПB *
С/П ИП9 * ИП8 + П8 ИП9 ИПB * П9
ИПA L0 32 ИП8 КП3 L1 25 8 П0 ИП7
ПП 93 П1 ИП6 ПП 93 ИП5 + П6 ИП1
ИП4 + П7 ИП4 ИП6 С/П П4 ИП5 ИП7 С/П
П5 ИП4 ИП6 П4 <-> П6 ИП5 ИП7 П5 <->
П7 БП 00 ИПC / [x] КП0 Вx {x} ИПC
* ИПD * В/О</syntaxhighlight>
 
Code for the second module:
<syntaxhighlight lang="text">П1 <-> П2 Сx П3 1 П4 19 П0 ИП1
2 / [x] П1 Вx {x} ИП2 2 / [x]
П2 Вx {x} <-> -> - x#0 33 ИП4 ИП3
+ П3 ИП4 ^ + П4 L0 10 ИП3 С/П
БП 00</syntaxhighlight>
 
<u>Instruction</u>:
 
Input is double-byte digits. Open text is in registers Р4 - Р7; and Р7 is low digit, Р4 is high digit.
 
After starting the program enter digits of key; first high, then low digit. After this, a table element changes to the line number in sequence (0 to 7) and the number of columns specified in the indicator.
 
After that, in the registers X and Y will be located two numbers that are entered in the second program. The result is shown on the display is returned to the first program. Then this action is repeated again.
 
In addition, the number originally entered: РB = 16, РC = 32, РD = 2048, РE = 65536.
 
=={{header|Nim}}==
Algorithm inspired from C, Go, etc.
The Sboxes are computed at compile time.
<syntaxhighlight lang="nim">import sequtils, strutils
 
const
K1 = [byte 4, 10, 9, 2, 13, 8, 0, 14, 6, 11, 1, 12, 7, 15, 5, 3]
K2 = [byte 14, 11, 4, 12, 6, 13, 15, 10, 2, 3, 8, 1, 0, 7, 5, 9]
K3 = [byte 5, 8, 1, 13, 10, 3, 4, 2, 14, 15, 12, 7, 6, 0, 9, 11]
K4 = [byte 7, 13, 10, 1, 0, 8, 9, 15, 14, 4, 6, 12, 11, 2, 5, 3]
K5 = [byte 6, 12, 7, 1, 5, 15, 13, 8, 4, 10, 9, 14, 0, 3, 11, 2]
K6 = [byte 4, 11, 10, 0, 7, 2, 1, 13, 3, 6, 8, 5, 9, 12, 15, 14]
K7 = [byte 13, 11, 4, 1, 3, 15, 5, 9, 0, 10, 14, 7, 6, 8, 2, 12]
K8 = [byte 1, 15, 13, 0, 5, 7, 10, 4, 9, 2, 3, 14, 6, 11, 8, 12]
 
 
proc kboxInit: tuple[k87, k65, k43, k21: array[256, byte]] {.compileTime.} =
for i in 0 .. 255:
result.k87[i] = K8[i shr 4] shl 4 or K7[i and 15]
result.k65[i] = K6[i shr 4] shl 4 or K5[i and 15]
result.k43[i] = K4[i shr 4] shl 4 or K3[i and 15]
result.k21[i] = K2[i shr 4] shl 4 or K1[i and 15]
 
const (K87, K65, K43, K21) = kboxInit()
 
template rol(x: uint32; n: typed): uint32 =
x shl n or x shr (32 - n)
 
proc f(x: uint32): uint32 =
let x = K87[x shr 24 and 255].uint32 shl 24 or K65[x shr 16 and 255].uint32 shl 16 or
K43[x shr 8 and 255].uint32 shl 8 or K21[x and 255].uint32
result = x.rol(11)
 
proc mainStep(input: array[8, byte]; key: array[4, byte]): array[8, byte] =
let input32 = cast[array[2, uint32]](input)
let key = cast[uint32](key)
let val = f(key + input32[0]) xor input32[1]
result[0..3] = cast[array[4, byte]](val)
result[4..7] = input[0..3]
 
when isMainModule:
const
Input = [byte 0x21, 0x04, 0x3B, 0x04, 0x30, 0x04, 0x32, 0x04]
Key = [byte 0xF9, 0x04, 0xC1, 0xE2]
 
let output = mainStep(Input, Key)
echo mapIt(output, it.toHex).join(" ")</syntaxhighlight>
 
{{out}}
<pre>1F 88 CF 07 21 04 3B 04</pre>
 
=={{header|Perl}}==
{{trans|Raku}}
{{libheader|ntheory}}
<syntaxhighlight lang="perl">use strict;
use warnings;
use ntheory 'fromdigits';
 
<lang perl6>
# sboxes from http://en.wikipedia.org/wiki/GOST_(block_cipher)
my \sboxes@sbox = (
[4, 10, 9, 2, 13, 8, 0, 14, 6, 11, 1, 12, 7, 15, 5, 3],
[14, 11, 4, 12, 6, 13, 15, 10, 2, 3, 8, 1, 0, 7, 5, 9],
Line 260 ⟶ 983:
[4, 11, 10, 0, 7, 2, 1, 13, 3, 6, 8, 5, 9, 12, 15, 14],
[13, 11, 4, 1, 3, 15, 5, 9, 0, 10, 14, 7, 6, 8, 2, 12],
[1, 15, 13, 0, 5, 7, 10, 4, 9, 2, 3, 14, 6, 11, 8, 12],
);
 
sub rol32 {
sub infix:<rol³²>(\y, \n) { (y +< n) % 2**32 +| (y +> (32-n)) }
my($y, $n) = @_;
($y << $n) % 2**32 | ($y >> (32 - $n))
}
 
sub gost-round(\R, \K)GOST_round {
my \a = ($R, + $K) %= 2**32@_;
my \b$a = :16[ sboxes[($_][(aR +> (4*$_)K) % 16] for 7...0 ]2**32;
my $b = fromdigits([map { $sbox[$_][($a >> (4*$_))%16] } reverse 0..7],16);
my \c = b rol³² 11;
crol32($b,11);
}
 
sub feistel_step {
sub feistel-step(&F, \L, \R, \K) {
my(R$F, $L, +^ F($R, $K)) = @_;
$R, $L ^ &$F($R, $K)
}
 
my @input = (0x21, 0x04, 0x3B, 0x04, 0x30, 0x04, 0x32, 0x04);
my @key = (0xF9, 0x04, 0xC1, 0xE2);
 
my $R = fromdigits([reverse @input[0..3]], 256); # 1st half
my $L = fromdigits([reverse @input[4..7]], 256); # 2nd half
my $K = fromdigits([reverse @key ], 256);
 
($L,$R) = feistel_step(\&GOST_round, $L, $R, $K);
 
printf '%02X ', (($L << 32) + $R >> (8*$_))%256 for 0..7;
print "\n";</syntaxhighlight>
{{out}}
<pre>1F 88 CF 07 21 04 3B 04</pre>
 
=={{header|Phix}}==
{{trans|D}}
<!--<syntaxhighlight lang="phix">(phixonline)-->
<span style="color: #008080;">with</span> <span style="color: #008080;">javascript_semantics</span>
<span style="color: #008080;">constant</span> <span style="color: #000000;">cbrf</span> <span style="color: #0000FF;">=</span> <span style="color: #0000FF;">{</span>
<span style="color: #0000FF;">{</span> <span style="color: #000000;">4</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">10</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">9</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">2</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">13</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">8</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">0</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">14</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">6</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">11</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">1</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">12</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">7</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">15</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">5</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">3</span><span style="color: #0000FF;">},</span>
<span style="color: #0000FF;">{</span><span style="color: #000000;">14</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">11</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">4</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">12</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">6</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">13</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">15</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">10</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">2</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">3</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">8</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">1</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">0</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">7</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">5</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">9</span><span style="color: #0000FF;">},</span>
<span style="color: #0000FF;">{</span> <span style="color: #000000;">5</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">8</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">1</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">13</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">10</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">3</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">4</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">2</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">14</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">15</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">12</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">7</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">6</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">0</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">9</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">11</span><span style="color: #0000FF;">},</span>
<span style="color: #0000FF;">{</span> <span style="color: #000000;">7</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">13</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">10</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">1</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">0</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">8</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">9</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">15</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">14</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">4</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">6</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">12</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">11</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">2</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">5</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">3</span><span style="color: #0000FF;">},</span>
<span style="color: #0000FF;">{</span> <span style="color: #000000;">6</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">12</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">7</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">1</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">5</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">15</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">13</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">8</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">4</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">10</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">9</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">14</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">0</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">3</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">11</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">2</span><span style="color: #0000FF;">},</span>
<span style="color: #0000FF;">{</span> <span style="color: #000000;">4</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">11</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">10</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">0</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">7</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">2</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">1</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">13</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">3</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">6</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">8</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">5</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">9</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">12</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">15</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">14</span><span style="color: #0000FF;">},</span>
<span style="color: #0000FF;">{</span><span style="color: #000000;">13</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">11</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">4</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">1</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">3</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">15</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">5</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">9</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">0</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">10</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">14</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">7</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">6</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">8</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">2</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">12</span><span style="color: #0000FF;">},</span>
<span style="color: #0000FF;">{</span> <span style="color: #000000;">1</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">15</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">13</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">0</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">5</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">7</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">10</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">4</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">9</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">2</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">3</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">14</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">6</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">11</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">8</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">12</span><span style="color: #0000FF;">}}</span>
<span style="color: #008080;">function</span> <span style="color: #000000;">generate</span><span style="color: #0000FF;">(</span><span style="color: #004080;">integer</span> <span style="color: #000000;">k</span><span style="color: #0000FF;">)</span>
<span style="color: #004080;">sequence</span> <span style="color: #000000;">res</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">repeat</span><span style="color: #0000FF;">(</span><span style="color: #000000;">0</span><span style="color: #0000FF;">,</span><span style="color: #000000;">256</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">for</span> <span style="color: #000000;">i</span><span style="color: #0000FF;">=</span><span style="color: #000000;">1</span> <span style="color: #008080;">to</span> <span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">res</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">do</span>
<span style="color: #004080;">integer</span> <span style="color: #000000;">hdx</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">floor</span><span style="color: #0000FF;">((</span><span style="color: #000000;">i</span><span style="color: #0000FF;">-</span><span style="color: #000000;">1</span><span style="color: #0000FF;">)/</span><span style="color: #000000;">16</span><span style="color: #0000FF;">)+</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span>
<span style="color: #000000;">ldx</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">and_bits</span><span style="color: #0000FF;">(</span><span style="color: #000000;">i</span><span style="color: #0000FF;">-</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span><span style="color: #000000;">#F</span><span style="color: #0000FF;">)+</span><span style="color: #000000;">1</span>
<span style="color: #000000;">res</span><span style="color: #0000FF;">[</span><span style="color: #000000;">i</span><span style="color: #0000FF;">]</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">or_bits</span><span style="color: #0000FF;">(</span><span style="color: #000000;">cbrf</span><span style="color: #0000FF;">[</span><span style="color: #000000;">k</span><span style="color: #0000FF;">][</span><span style="color: #000000;">hdx</span><span style="color: #0000FF;">]*</span><span style="color: #000000;">#10</span><span style="color: #0000FF;">,</span><span style="color: #000000;">cbrf</span><span style="color: #0000FF;">[</span><span style="color: #000000;">k</span><span style="color: #0000FF;">-</span><span style="color: #000000;">1</span><span style="color: #0000FF;">][</span><span style="color: #000000;">ldx</span><span style="color: #0000FF;">])</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
<span style="color: #008080;">return</span> <span style="color: #000000;">res</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">function</span>
<span style="color: #008080;">constant</span> <span style="color: #000000;">k87</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">generate</span><span style="color: #0000FF;">(</span><span style="color: #000000;">8</span><span style="color: #0000FF;">),</span>
<span style="color: #000000;">k65</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">generate</span><span style="color: #0000FF;">(</span><span style="color: #000000;">6</span><span style="color: #0000FF;">),</span>
<span style="color: #000000;">k43</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">generate</span><span style="color: #0000FF;">(</span><span style="color: #000000;">4</span><span style="color: #0000FF;">),</span>
<span style="color: #000000;">k21</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">generate</span><span style="color: #0000FF;">(</span><span style="color: #000000;">2</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">function</span> <span style="color: #000000;">r32</span><span style="color: #0000FF;">(</span><span style="color: #004080;">atom</span> <span style="color: #000000;">a</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">if</span> <span style="color: #000000;">a</span><span style="color: #0000FF;"><</span><span style="color: #000000;">0</span> <span style="color: #008080;">then</span> <span style="color: #000000;">a</span><span style="color: #0000FF;">+=</span><span style="color: #000000;">#100000000</span> <span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
<span style="color: #008080;">return</span> <span style="color: #7060A8;">remainder</span><span style="color: #0000FF;">(</span><span style="color: #000000;">a</span><span style="color: #0000FF;">,</span><span style="color: #000000;">#100000000</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">function</span>
<span style="color: #008080;">function</span> <span style="color: #000000;">mainstep</span><span style="color: #0000FF;">(</span><span style="color: #004080;">sequence</span> <span style="color: #000000;">input</span><span style="color: #0000FF;">,</span> <span style="color: #004080;">atom</span> <span style="color: #000000;">key</span><span style="color: #0000FF;">)</span>
<span style="color: #004080;">atom</span> <span style="color: #000000;">s</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">r32</span><span style="color: #0000FF;">(</span><span style="color: #000000;">input</span><span style="color: #0000FF;">[</span><span style="color: #000000;">1</span><span style="color: #0000FF;">]+</span><span style="color: #000000;">key</span><span style="color: #0000FF;">)</span>
<span style="color: #000000;">s</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">r32</span><span style="color: #0000FF;">(</span><span style="color: #7060A8;">or_all</span><span style="color: #0000FF;">({</span><span style="color: #000000;">k87</span><span style="color: #0000FF;">[</span><span style="color: #7060A8;">and_bits</span><span style="color: #0000FF;">(</span><span style="color: #7060A8;">floor</span><span style="color: #0000FF;">(</span><span style="color: #000000;">s</span><span style="color: #0000FF;">/</span><span style="color: #000000;">#1000000</span><span style="color: #0000FF;">),</span><span style="color: #000000;">#FF</span><span style="color: #0000FF;">)+</span><span style="color: #000000;">1</span><span style="color: #0000FF;">]*</span><span style="color: #000000;">#1000000</span><span style="color: #0000FF;">,</span>
<span style="color: #000000;">k65</span><span style="color: #0000FF;">[</span><span style="color: #7060A8;">and_bits</span><span style="color: #0000FF;">(</span><span style="color: #7060A8;">floor</span><span style="color: #0000FF;">(</span><span style="color: #000000;">s</span><span style="color: #0000FF;">/</span><span style="color: #000000;">#0010000</span><span style="color: #0000FF;">),</span><span style="color: #000000;">#FF</span><span style="color: #0000FF;">)+</span><span style="color: #000000;">1</span><span style="color: #0000FF;">]*</span><span style="color: #000000;">#0010000</span><span style="color: #0000FF;">,</span>
<span style="color: #000000;">k43</span><span style="color: #0000FF;">[</span><span style="color: #7060A8;">and_bits</span><span style="color: #0000FF;">(</span><span style="color: #7060A8;">floor</span><span style="color: #0000FF;">(</span><span style="color: #000000;">s</span><span style="color: #0000FF;">/</span><span style="color: #000000;">#0000100</span><span style="color: #0000FF;">),</span><span style="color: #000000;">#FF</span><span style="color: #0000FF;">)+</span><span style="color: #000000;">1</span><span style="color: #0000FF;">]*</span><span style="color: #000000;">#0000100</span><span style="color: #0000FF;">,</span>
<span style="color: #000000;">k21</span><span style="color: #0000FF;">[</span><span style="color: #7060A8;">and_bits</span><span style="color: #0000FF;">(</span><span style="color: #7060A8;">floor</span><span style="color: #0000FF;">(</span><span style="color: #000000;">s</span><span style="color: #0000FF;">/</span><span style="color: #000000;">#0000001</span><span style="color: #0000FF;">),</span><span style="color: #000000;">#FF</span><span style="color: #0000FF;">)+</span><span style="color: #000000;">1</span><span style="color: #0000FF;">]*</span><span style="color: #000000;">#0000001</span><span style="color: #0000FF;">}))</span>
<span style="color: #000000;">s</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">r32</span><span style="color: #0000FF;">(</span><span style="color: #000000;">s</span><span style="color: #0000FF;">*</span><span style="color: #7060A8;">power</span><span style="color: #0000FF;">(</span><span style="color: #000000;">2</span><span style="color: #0000FF;">,</span><span style="color: #000000;">11</span><span style="color: #0000FF;">))+</span><span style="color: #7060A8;">floor</span><span style="color: #0000FF;">(</span><span style="color: #000000;">s</span><span style="color: #0000FF;">/</span><span style="color: #7060A8;">power</span><span style="color: #0000FF;">(</span><span style="color: #000000;">2</span><span style="color: #0000FF;">,</span><span style="color: #000000;">32</span><span style="color: #0000FF;">-</span><span style="color: #000000;">11</span><span style="color: #0000FF;">))</span>
<span style="color: #000000;">s</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">xor_bits</span><span style="color: #0000FF;">(</span><span style="color: #000000;">s</span><span style="color: #0000FF;">,</span><span style="color: #000000;">input</span><span style="color: #0000FF;">[</span><span style="color: #000000;">2</span><span style="color: #0000FF;">])</span>
<span style="color: #008080;">return</span> <span style="color: #0000FF;">{</span><span style="color: #000000;">s</span><span style="color: #0000FF;">,</span><span style="color: #000000;">input</span><span style="color: #0000FF;">[</span><span style="color: #000000;">1</span><span style="color: #0000FF;">]}</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">function</span>
<span style="color: #004080;">sequence</span> <span style="color: #000000;">res</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">mainstep</span><span style="color: #0000FF;">({</span><span style="color: #000000;">#043B0421</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">#04320430</span><span style="color: #0000FF;">},</span> <span style="color: #000000;">#E2C104F9</span><span style="color: #0000FF;">)</span>
<span style="color: #7060A8;">printf</span><span style="color: #0000FF;">(</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"%08x %08x\n"</span><span style="color: #0000FF;">,</span><span style="color: #000000;">res</span><span style="color: #0000FF;">)</span>
<span style="color: #000080;font-style:italic;">--or, for other-endian:</span>
<span style="color: #004080;">sequence</span> <span style="color: #000000;">s</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">sprintf</span><span style="color: #0000FF;">(</span><span style="color: #008000;">"%08x"</span><span style="color: #0000FF;">,</span><span style="color: #000000;">res</span><span style="color: #0000FF;">[</span><span style="color: #000000;">1</span><span style="color: #0000FF;">]),</span>
<span style="color: #000000;">t</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">sprintf</span><span style="color: #0000FF;">(</span><span style="color: #008000;">"%08x"</span><span style="color: #0000FF;">,</span><span style="color: #000000;">res</span><span style="color: #0000FF;">[</span><span style="color: #000000;">2</span><span style="color: #0000FF;">])</span>
<span style="color: #000000;">s</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">reverse</span><span style="color: #0000FF;">(</span><span style="color: #7060A8;">split</span><span style="color: #0000FF;">(</span><span style="color: #7060A8;">join_by</span><span style="color: #0000FF;">(</span><span style="color: #000000;">s</span><span style="color: #0000FF;">,</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span><span style="color: #000000;">2</span><span style="color: #0000FF;">,</span><span style="color: #008000;">""</span><span style="color: #0000FF;">,</span><span style="color: #008000;">" "</span><span style="color: #0000FF;">)))</span>
<span style="color: #000000;">t</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">reverse</span><span style="color: #0000FF;">(</span><span style="color: #7060A8;">split</span><span style="color: #0000FF;">(</span><span style="color: #7060A8;">join_by</span><span style="color: #0000FF;">(</span><span style="color: #000000;">t</span><span style="color: #0000FF;">,</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span><span style="color: #000000;">2</span><span style="color: #0000FF;">,</span><span style="color: #008000;">""</span><span style="color: #0000FF;">,</span><span style="color: #008000;">" "</span><span style="color: #0000FF;">)))</span>
<span style="color: #0000FF;">?{</span><span style="color: #000000;">s</span><span style="color: #0000FF;">,</span><span style="color: #000000;">t</span><span style="color: #0000FF;">}</span>
<!--</syntaxhighlight>-->
{{out}}
<pre>
07CF881F 043B0421
{{"1F","88","CF","07"},{"21","04","3B","04"}}
</pre>
 
=={{header|PicoLisp}}==
{{trans|C}}
<syntaxhighlight lang="picolisp">(setq K1 (13 2 8 4 6 15 11 1 10 9 3 14 5 0 12 7))
(setq K2 ( 4 11 2 14 15 0 8 13 3 12 9 7 5 10 6 1))
(setq K3 (12 1 10 15 9 2 6 8 0 13 3 4 14 7 5 11))
(setq K4 ( 2 12 4 1 7 10 11 6 8 5 3 15 13 0 14 9))
(setq K5 ( 7 13 14 3 0 6 9 10 1 2 8 5 11 12 4 15))
(setq K6 (10 0 9 14 6 3 15 5 1 13 12 7 11 4 2 8))
(setq K7 (15 1 8 14 6 11 3 4 9 7 2 13 12 0 5 10))
(setq K8 (14 4 13 1 2 15 11 8 3 10 6 12 5 9 0 7))
 
(setq K21
(mapcar
'((N)
(|
(>> -4 (get K2 (inc (>> 4 N))))
(get K1 (inc (& N 15))) ) )
(range 0 255) ) )
 
(setq K43
(mapcar
'((N)
(|
(>> -4 (get K4 (inc (>> 4 N))))
(get K3 (inc (& N 15))) ) )
(range 0 255) ) )
 
(setq K65
(mapcar
'((N)
(|
(>> -4 (get K6 (inc (>> 4 N))))
(get K5 (inc (& N 15))) ) )
(range 0 255) ) )
 
(setq K87
(mapcar
'((N)
(|
(>> -4 (get K8 (inc (>> 4 N))))
(get K7 (inc (& N 15))) ) )
(range 0 255) ) )
(de leftRotate (X C)
(|
(& `(hex "FFFFFFFF") (>> (- C) X))
(>> (- 32 C) X) ) )
 
(de f (X)
(leftRotate
(apply
|
(mapcar
'((Lst N)
(>>
N
(get
(val Lst)
(inc (& 255 (>> (abs N) X))) ) ) )
'(K87 K65 K43 K21)
(-24 -16 -8 0) ) )
11 ) )
(bye)</syntaxhighlight>
 
=={{header|Python}}==
{{trans|C}}
<syntaxhighlight lang="python">
k8 = [ 14, 4, 13, 1, 2, 15, 11, 8, 3, 10, 6, 12, 5, 9, 0, 7 ]
k7 = [ 15, 1, 8, 14, 6, 11, 3, 4, 9, 7, 2, 13, 12, 0, 5, 10 ]
k6 = [ 10, 0, 9, 14, 6, 3, 15, 5, 1, 13, 12, 7, 11, 4, 2, 8 ]
k5 = [ 7, 13, 14, 3, 0, 6, 9, 10, 1, 2, 8, 5, 11, 12, 4, 15 ]
k4 = [ 2, 12, 4, 1, 7, 10, 11, 6, 8, 5, 3, 15, 13, 0, 14, 9 ]
k3 = [ 12, 1, 10, 15, 9, 2, 6, 8, 0, 13, 3, 4, 14, 7, 5, 11 ]
k2 = [ 4, 11, 2, 14, 15, 0, 8, 13, 3, 12, 9, 7, 5, 10, 6, 1 ]
k1 = [ 13, 2, 8, 4, 6, 15, 11, 1, 10, 9, 3, 14, 5, 0, 12, 7 ]
k87 = [0] * 256
k65 = [0] * 256
k43 = [0] * 256
k21 = [0] * 256
def kboxinit():
for i in range(256):
k87[i] = k8[i >> 4] << 4 | k7[i & 15]
k65[i] = k6[i >> 4] << 4 | k5[i & 15]
k43[i] = k4[i >> 4] << 4 | k3[i & 15]
k21[i] = k2[i >> 4] << 4 | k1[i & 15]
def f(x):
x = ( k87[x>>24 & 255] << 24 | k65[x>>16 & 255] << 16 |
k43[x>> 8 & 255] << 8 | k21[x & 255] )
return x<<11 | x>>(32-11)</syntaxhighlight>
 
=={{header|Racket}}==
This is a direct translation of the C code, but I have no idea if that code is correct, or a way to test it. (I suspect that it isn't, at least since the table has different numbers than the wikipedia article...)
<syntaxhighlight lang="racket">
#lang racket
 
(define k8 (bytes 14 4 13 1 2 15 11 8 3 10 6 12 5 9 0 7))
(define k7 (bytes 15 1 8 14 6 11 3 4 9 7 2 13 12 0 5 10))
(define k6 (bytes 10 0 9 14 6 3 15 5 1 13 12 7 11 4 2 8))
(define k5 (bytes 7 13 14 3 0 6 9 10 1 2 8 5 11 12 4 15))
(define k4 (bytes 2 12 4 1 7 10 11 6 8 5 3 15 13 0 14 9))
(define k3 (bytes 12 1 10 15 9 2 6 8 0 13 3 4 14 7 5 11))
(define k2 (bytes 4 11 2 14 15 0 8 13 3 12 9 7 5 10 6 1))
(define k1 (bytes 13 2 8 4 6 15 11 1 10 9 3 14 5 0 12 7))
 
(define (mk-k k2 k1)
(list->bytes (for*/list ([i 16] [j 16]) (+ (* (bytes-ref k2 i) 16) (bytes-ref k1 j)))))
 
(define k87 (mk-k k8 k7))
(define k65 (mk-k k6 k5))
(define k43 (mk-k k4 k3))
(define k21 (mk-k k2 k1))
 
(define (f x)
(define bs (integer->integer-bytes x 4 #f #f))
(define x*
(bitwise-and #xFFFFFFFF
(integer-bytes->integer
(bytes (bytes-ref k21 (bytes-ref bs 0))
(bytes-ref k43 (bytes-ref bs 1))
(bytes-ref k65 (bytes-ref bs 2))
(bytes-ref k87 (bytes-ref bs 3)))
#f #f)))
(bitwise-ior (bitwise-and #xFFFFFFFF (arithmetic-shift x* 11))
(arithmetic-shift x* (- 11 32))))
</syntaxhighlight>
 
=={{header|Raku}}==
(formerly Perl 6)
{{works with|rakudo|2012-10-30}}
Implemented to match explanation on Discussion page:
 
<syntaxhighlight lang="raku" line># sboxes from http://en.wikipedia.org/wiki/GOST_(block_cipher)
constant sbox =
[4, 10, 9, 2, 13, 8, 0, 14, 6, 11, 1, 12, 7, 15, 5, 3],
[14, 11, 4, 12, 6, 13, 15, 10, 2, 3, 8, 1, 0, 7, 5, 9],
[5, 8, 1, 13, 10, 3, 4, 2, 14, 15, 12, 7, 6, 0, 9, 11],
[7, 13, 10, 1, 0, 8, 9, 15, 14, 4, 6, 12, 11, 2, 5, 3],
[6, 12, 7, 1, 5, 15, 13, 8, 4, 10, 9, 14, 0, 3, 11, 2],
[4, 11, 10, 0, 7, 2, 1, 13, 3, 6, 8, 5, 9, 12, 15, 14],
[13, 11, 4, 1, 3, 15, 5, 9, 0, 10, 14, 7, 6, 8, 2, 12],
[1, 15, 13, 0, 5, 7, 10, 4, 9, 2, 3, 14, 6, 11, 8, 12];
sub infix:<rol³²>(\y, \n) { (y +< n) % 2**32 +| (y +> (32 - n)) }
sub ГОСТ-round(\R, \K) {
my \a = (R + K) % 2**32;
my \b = :16[ sbox[$_][(a +> (4 * $_)) % 16] for 7...0 ];
b rol³² 11;
}
sub feistel-step(&F, \L, \R, \K) { R, L +^ F(R, K) }
my @input = 0x21, 0x04, 0x3B, 0x04, 0x30, 0x04, 0x32, 0x04;
my @key = 0xF9, 0x04, 0xC1, 0xE2;
my ($L,$R) = @input.reverse.map: { :256[$^a,$^b,$^c,$^d] }
my ($K ) = @key .reverse.map: { :256[$^a,$^b,$^c,$^d] }
($L,$R) = feistel-step(&ГОСТ-round, $L, $R, $K);
 
say [ ($L +< 32 + $R X+> (0, 8 ... 56)) X% 256 ].fmt('%02X');</syntaxhighlight>
my ($L,$R) = @input.reverse.map: { :256[$^a,$^b,$^c,$^d] };
my ($K ) = @key\ .reverse.map: { :256[$^a,$^b,$^c,$^d] };
 
{{out}}
($L,$R) = feistel-step(&gost-round, $L, $R, $K);
<pre>1F 88 CF 07 21 04 3B 04</pre>
 
=={{header|REXX}}==
# reproduce example output from Discussion page
{{trans|BBC BASIC}}
say (((($L +< 32 + $R) +> (8*$_)) % 256).fmt('[%02X]') for 0..7).join;
<syntaxhighlight lang="rexx">/*REXX program implements main step GOST 28147-89 based on a Feistel network. */
</lang>
numeric digits 12 /* ┌── a list of 4─bit S─box values used by */
/* ↓ the Central Bank of Russian Federation.*/
@.0 = 4 10 9 2 13 8 0 14 6 11 1 12 7 15 5 3
@.1 = 14 11 4 12 6 13 15 10 2 3 8 1 0 7 5 9
@.2 = 5 8 1 13 10 3 4 2 14 15 12 7 6 0 9 11
@.3 = 7 13 10 1 0 8 9 15 14 4 6 12 11 2 5 3
@.4 = 6 12 7 1 5 15 13 8 4 10 9 14 0 3 11 2
@.5 = 4 11 10 0 7 2 1 13 3 6 8 5 9 12 15 14
@.6 = 13 11 4 1 3 15 5 9 0 10 14 7 6 8 2 12
@.7 = 1 15 13 0 5 7 10 4 9 2 3 14 6 11 8 12
/* [↓] build the sub-keys array from above. */
do r=0 for 8; do c=0 for 16; !.r.c=word(@.r, c + 1); end; end
z=0
#1=x2d( 43b0421 ); #2=x2d( 4320430 ); k=#1 + x2d( 0e2c104f9 )
do while k > x2d( 7ffFFffF ); k=k - 2**32; end
do while k < x2d( 80000000 ); k=k + 2**32; end
 
do j=0 for 4; jj=j + j; jjp=jj + 1 /*calculate the array'a "subscripts". */
$=x2d( right( d2x( k % 2 ** (j * 8) ), 2) )
cm=$ // 16; cd=$ % 16 /*perform modulus and integer division.*/
z=z + (!.jj.cm + 16 * !.jjp.cd) * 2**(j*8)
end /*i*/ /* [↑] encryption algorithm for S-box.*/
/* [↓] encryption algorithm round. */
k = c2d( bitxor( bitor( d2c(z * 2**11, 4), d2c(z % 2**21, 4) ), d2c(#2, 4) ) )
say center(d2x(k) ' ' d2x(#1), 79) /*stick a fork in it, we're all done. */</syntaxhighlight>
{{out|output|:}}
<pre>
7CF881F 43B0421
</pre>
 
=={{header|RPL}}==
{{ trans|Nim}}
« { { 4 10 9 2 13 8 0 14 6 11 1 12 7 15 5 3 }
{ 14 11 4 12 6 13 15 10 2 3 8 1 0 7 5 9 }
{ 5 8 1 13 10 3 4 2 14 15 12 7 6 0 9 11 }
{ 7 13 10 1 0 8 9 15 14 4 6 12 11 2 5 3 }
{ 6 12 7 1 5 15 13 8 4 10 9 14 0 3 11 2 }
{ 4 11 10 0 7 2 1 13 3 6 8 5 9 12 15 14 }
{ 13 11 4 1 3 15 5 9 0 10 14 7 6 8 2 12 }
{ 1 15 13 0 5 7 10 4 9 2 3 14 6 11 8 12 } }
« R→B » DOLIST 'K' STO
{ K21 K43 K65 K87 } 1 « { } SWAP STO » DOLIST
0 255 '''FOR''' j
1 4 '''FOR''' n
'K' n 2 * GET j 16 / IP 1 + GET 16 *
'K' n 2 * 1 - GET j 16 MOD 1 + GET OR
'''NEXT'''
4 →LIST { K21 K43 K65 K87 } SWAP STO+
'''NEXT'''
» '<span style="color:blue">KBOXINIT</span>' STO
« { }
'''WHILE''' #0h ≠ '''REPEAT'''
OVER #255d AND SWAP OVER + SWAP SRB
'''END''' SWAP DROP
» '<span style="color:blue">B→LIST</span>' STO
« « SWAP SLB OR » → input key cast
« key REVLIST cast STREAM <span style="color:grey">@ convert key into a little-endian integer</span>
input 1 4 SUB REVLIST cast STREAM + <span style="color:blue">B→LIST</span> <span style="color:grey">@ same for input part 1, then add and back to list format</span>
{ K21 K43 K65 K87 } SWAP B→R 1 ADD GET <span style="color:grey">@ replace bytes according to the table</span>
REVLIST cast STREAM <span style="color:grey">@ back to little-endian format</span>
RLB RL RL RL <span style="color:blue">B→LIST</span> <span style="color:grey">@ roll 11 bits, back to list format</span>
input 5 8 SUB XOR <span style="color:grey">@ add part 2</span>
input 1 4 SUB + <span style="color:grey">@ append part 1</span>
» » '<span style="color:blue">MAINSTEP</span>' STO
« 32 STWS HEX
<span style="color:blue">KBOXINIT</span>
{ #21h #4h #3Bh #4h #30h #4h #32h #4h } { #F9h #4h #C1h #E2h } <span style="color:blue">MAINSTEP</span>
» '<span style="color:blue">TASK</span>' STO
{{out}}
<pre>
1: { # 1Fh # 88h # CFh # 7h # 21h # 4h # 3Bh # 4h }
[1F][88][CF][07][21][04][3B][04]
</pre>
 
=={{header|Rust}}==
<syntaxhighlight lang="rust">use std::convert::TryInto;
use std::env;
use std::num::Wrapping;
 
const REPLACEMENT_TABLE: [[u8; 16]; 8] = [
[4, 10, 9, 2, 13, 8, 0, 14, 6, 11, 1, 12, 7, 15, 5, 3],
[14, 11, 4, 12, 6, 13, 15, 10, 2, 3, 8, 1, 0, 7, 5, 9],
[5, 8, 1, 13, 10, 3, 4, 2, 14, 15, 12, 7, 6, 0, 9, 11],
[7, 13, 10, 1, 0, 8, 9, 15, 14, 4, 6, 12, 11, 2, 5, 3],
[6, 12, 7, 1, 5, 15, 13, 8, 4, 10, 9, 14, 0, 3, 11, 2],
[4, 11, 10, 0, 7, 2, 1, 13, 3, 6, 8, 5, 9, 12, 15, 14],
[13, 11, 4, 1, 3, 15, 5, 9, 0, 10, 14, 7, 6, 8, 2, 12],
[1, 15, 13, 0, 5, 7, 10, 4, 9, 2, 3, 14, 6, 11, 8, 12],
];
const KEYS: [u32; 8] = [
0xE2C1_04F9,
0xE41D_7CDE,
0x7FE5_E857,
0x0602_65B4,
0x281C_CC85,
0x2E2C_929A,
0x4746_4503,
0xE00_CE510,
];
 
fn main() {
let args: Vec<String> = env::args().collect();
if args.len() < 2 {
let plain_text: Vec<u8> = vec![0x04, 0x3B, 0x04, 0x21, 0x04, 0x32, 0x04, 0x30];
println!(
"Before one step: {}\n",
plain_text
.iter()
.cloned()
.fold("".to_string(), |b, y| b + &format!("{:02X} ", y))
);
let encoded_text = main_step(plain_text, KEYS[0]);
println!(
"After one step : {}\n",
encoded_text
.iter()
.cloned()
.fold("".to_string(), |b, y| b + &format!("{:02X} ", y))
);
} else {
let mut t = args[1].clone(); // "They call him... Баба Яга"
t += &" ".repeat((8 - t.len() % 8) % 8);
let text_bytes = t.bytes().collect::<Vec<_>>();
let plain_text = text_bytes.chunks(8).collect::<Vec<_>>();
println!(
"Plain text : {}\n",
plain_text.iter().cloned().fold("".to_string(), |a, x| a
+ "["
+ &x.iter()
.fold("".to_string(), |b, y| b + &format!("{:02X} ", y))[..23]
+ "]")
);
let encoded_text = plain_text
.iter()
.map(|c| encode(c.to_vec()))
.collect::<Vec<_>>();
println!(
"Encoded text: {}\n",
encoded_text.iter().cloned().fold("".to_string(), |a, x| a
+ "["
+ &x.into_iter()
.fold("".to_string(), |b, y| b + &format!("{:02X} ", y))[..23]
+ "]")
);
let decoded_text = encoded_text
.iter()
.map(|c| decode(c.to_vec()))
.collect::<Vec<_>>();
println!(
"Decoded text: {}\n",
decoded_text.iter().cloned().fold("".to_string(), |a, x| a
+ "["
+ &x.into_iter()
.fold("".to_string(), |b, y| b + &format!("{:02X} ", y))[..23]
+ "]")
);
let recovered_text =
String::from_utf8(decoded_text.iter().cloned().flatten().collect::<Vec<_>>()).unwrap();
println!("Recovered text: {}\n", recovered_text);
}
}
 
fn encode(text_block: Vec<u8>) -> Vec<u8> {
let mut step = text_block;
for i in 0..24 {
step = main_step(step, KEYS[i % 8]);
}
for i in (0..8).rev() {
step = main_step(step, KEYS[i]);
}
step
}
 
fn decode(text_block: Vec<u8>) -> Vec<u8> {
let mut step = text_block[4..].to_vec();
let mut temp = text_block[..4].to_vec();
step.append(&mut temp);
for key in &KEYS {
step = main_step(step, *key);
}
for i in (0..24).rev() {
step = main_step(step, KEYS[i % 8]);
}
let mut ans = step[4..].to_vec();
let mut temp = step[..4].to_vec();
ans.append(&mut temp);
ans
}
 
fn main_step(text_block: Vec<u8>, key_element: u32) -> Vec<u8> {
let mut n = text_block;
let mut s = (Wrapping(
u32::from(n[0]) << 24 | u32::from(n[1]) << 16 | u32::from(n[2]) << 8 | u32::from(n[3]),
) + Wrapping(key_element))
.0;
let mut new_s: u32 = 0;
for mid in 0..4 {
let cell = (s >> (mid << 3)) & 0xFF;
new_s += (u32::from(REPLACEMENT_TABLE[(mid * 2) as usize][(cell & 0x0f) as usize])
+ (u32::from(REPLACEMENT_TABLE[(mid * 2 + 1) as usize][(cell >> 4) as usize]) << 4))
<< (mid << 3);
}
s = ((new_s << 11) + (new_s >> 21))
^ (u32::from(n[4]) << 24 | u32::from(n[5]) << 16 | u32::from(n[6]) << 8 | u32::from(n[7]));
n[4] = n[0];
n[5] = n[1];
n[6] = n[2];
n[7] = n[3];
n[0] = (s >> 24).try_into().unwrap();
n[1] = ((s >> 16) & 0xFF).try_into().unwrap();
n[2] = ((s >> 8) & 0xFF).try_into().unwrap();
n[3] = (s & 0xFF).try_into().unwrap();
n
}</syntaxhighlight>
{{out}}
<pre>
Without parameters:
 
Before one step: 04 3B 04 21 04 32 04 30
 
After one step : 07 CF 88 1F 04 3B 04 21
 
 
With parameter "They call him... Баба Яга"
 
Plain text : [54 68 65 79 20 63 61 6C][6C 20 68 69 6D 2E 2E 2E][20 D0 91 D0 B0 D0 B1 D0][B0 20 D0 AF D0 B3 D0 B0]
 
Encoded text: [D6 7C 52 4A EA 9A 58 2D][D9 81 F7 DA ED 89 46 25][0A 75 2D 89 59 8B 3D C4][53 DC D6 E2 79 B6 68 24]
 
Decoded text: [54 68 65 79 20 63 61 6C][6C 20 68 69 6D 2E 2E 2E][20 D0 91 D0 B0 D0 B1 D0][B0 20 D0 AF D0 B3 D0 B0]
 
Recovered text: They call him... Баба Яга
</pre>
 
=={{header|Tcl}}==
<langsyntaxhighlight lang="tcl">namespace eval ::GOST {
proc tcl::mathfunc::k {a b} {
variable ::GOST::replacementTable
Line 315 ⟶ 1,507:
return $textBlock
}
}</langsyntaxhighlight>
Note that only the <tt>idx</tt>'th row of the split-up <tt>textBlock</tt> (which contains the two pieces to intermingle/exchange at this step) is altered; it is the responsibility of the caller to iterate over all the steps through the entire plaintext/ciphertext.
 
Line 339 ⟶ 1,531:
* The contents of the segment registers unchanged.
 
<langsyntaxhighlight Asmlang="asm"> .386
.model flat
.code
Line 367 ⟶ 1,559:
ret
_gost32 endp
end</langsyntaxhighlight>
 
=={{header|Wren}}==
{{libheader|Wren-fmt}}
{{trans|Go}}
<syntaxhighlight lang="wren">import "./fmt" for Fmt
 
class GOST {
// assumes 's' is an 8 x 16 integer array
construct new(s) {
_k87 = List.filled(256, 0)
_k65 = List.filled(256, 0)
_k43 = List.filled(256, 0)
_k21 = List.filled(256, 0)
_enc = List.filled(8, 0)
for (i in 0..255) {
_k87[i] = s[7][i>>4]<<4 | s[6][i&15]
_k65[i] = s[5][i>>4]<<4 | s[4][i&15]
_k43[i] = s[3][i>>4]<<4 | s[2][i&15]
_k21[i] = s[1][i>>4]<<4 | s[0][i&15]
}
}
 
enc { _enc }
 
f(x) {
x = _k87[x>>24&255]<<24 | _k65[x>>16&255]<<16 | _k43[x>>8&255]<<8 | _k21[x&255]
return x<<11 | x>>(32-11)
}
 
mainStep(input, key) {
var key32 = GOST.u32(key)
var input1 = GOST.u32(input[0...4])
var input2 = GOST.u32(input[4..-1])
GOST.b4(f(key32+input1)^input2, enc)
for (i in 0..3) enc[i + 4] = input[i]
}
 
static u32(b) { b[0] | b[1]<<8 | b[2]<<16 | b[3]<<24 }
 
static b4(u, b) {
b[0] = u & 0xff
b[1] = (u >> 8) & 0xff
b[2] = (u >> 16) & 0xff
b[3] = (u >> 24) & 0xff
}
}
 
var cbrf = [
[ 4, 10, 9, 2, 13, 8, 0, 14, 6, 11, 1, 12, 7, 15, 5, 3],
[14, 11, 4, 12, 6, 13, 15, 10, 2, 3, 8, 1, 0, 7, 5, 9],
[ 5, 8, 1, 13, 10, 3, 4, 2, 14, 15, 12, 7, 6, 0, 9, 11],
[ 7, 13, 10, 1, 0, 8, 9, 15, 14, 4, 6, 12, 11, 2, 5, 3],
[ 6, 12, 7, 1, 5, 15, 13, 8, 4, 10, 9, 14, 0, 3, 11, 2],
[ 4, 11, 10, 0, 7, 2, 1, 13, 3, 6, 8, 5, 9, 12, 15, 14],
[13, 11, 4, 1, 3, 15, 5, 9, 0, 10, 14, 7, 6, 8, 2, 12],
[ 1, 15, 13, 0, 5, 7, 10, 4, 9, 2, 3, 14, 6, 11, 8, 12]
]
 
var input = [0x21, 0x04, 0x3b, 0x04, 0x30, 0x04, 0x32, 0x04]
var key = [0xf9, 0x04, 0xc1, 0xe2]
var g = GOST.new(cbrf)
g.mainStep(input, key)
for (b in g.enc) Fmt.write("[$02x]", b)
System.print()</syntaxhighlight>
 
{{out}}
<pre>
[1f][88][cf][07][21][04][3b][04]
</pre>
 
=={{header|zkl}}==
{{trans|C}}
{{trans|D}}
This could very well fail on a non-Intel endian-ness.
<syntaxhighlight lang="zkl">class GOST{
var [const] // Central Bank of Russian Federation S-Boxes
k8=Data(0,Int, 4, 10, 9, 2, 13, 8, 0, 14, 6, 11, 1, 12, 7, 15, 5, 3),
k7=Data(0,Int,14, 11, 4, 12, 6, 13, 15, 10, 2, 3, 8, 1, 0, 7, 5, 9),
k6=Data(0,Int, 5, 8, 1, 13, 10, 3, 4, 2, 14, 15, 12, 7, 6, 0, 9, 11),
k5=Data(0,Int, 7, 13, 10, 1, 0, 8, 9, 15, 14, 4, 6, 12, 11, 2, 5, 3),
k4=Data(0,Int, 6, 12, 7, 1, 5, 15, 13, 8, 4, 10, 9, 14, 0, 3, 11, 2),
k3=Data(0,Int, 4, 11, 10, 0, 7, 2, 1, 13, 3, 6, 8, 5, 9, 12, 15, 14),
k2=Data(0,Int,13, 11, 4, 1, 3, 15, 5, 9, 0, 10, 14, 7, 6, 8, 2, 12),
k1=Data(0,Int, 1, 15, 13, 0, 5, 7, 10, 4, 9, 2, 3, 14, 6, 11, 8, 12);
fcn generate(ka,kb)
{ (0).pump(256,Data,'wrap(i){ kb[i/0x10]*0x10 + ka[i%0x10] }) }
var [const] k87=generate(k8,k7), k65=generate(k6,k5),
k43=generate(k4,k3), k21=generate(k2,k1);
 
fcn f(x){ // int --> int
x3,x2,x1,x0:=x.toLittleEndian(4);
x=k87[x3] + k65[x2]*0x|100 + k43[x1]*0x1|0000 + k21[x0]*0x100|0000;
x.shiftLeft(11) + x.shiftRight(21); // roll left 11 bits, leaving bits on top
}
 
fcn mainStep(input,key){ // input is stream of bytes, little endian 32 bit words
r:=Data();
foreach idx in ([0..input.len()-1,8]){
w0:=input.toLittleEndian(idx, 4);
w1:=input.toLittleEndian(idx+4,4);
r.write(f(key+w0).bitXor(w1).toLittleEndian(4),w0.toLittleEndian(4));
}
r
}}</syntaxhighlight>
<syntaxhighlight lang="zkl"> // Example from the talk page (little endian byte stream)
input:=Data(0,Int,0x21, 0x04, 0x3B, 0x04, 0x30, 0x04, 0x32, 0x04);
key := 0xE2|C1|04|F9; // big endian
 
GOST.mainStep(input,key).bytes().apply("[%02x]".fmt).concat().println();</syntaxhighlight>
{{out}}
<pre>[1f][88][cf][07][21][04][3b][04]</pre>
 
{{omit from|GUISS}}
{{omit from|Lilypond}}
{{omit from|Stata}}
{{omit from|TPP}}