Executando verificação de segurança...
Em resposta a [Não disponível]
1

Que interessante! Essa postagem está ganhando pontos negativos "numa velocidade..." (o usuário que a postou está perdendo Tabcoins). Qual seria o motivo de estar sendo negativada com tanta frequência?

Outro detalhe diz respeito à pontuação. No momento em que marcavada -10, o Alt-text indicava -12 | +1 (8% achou relevante). Esta totalização não deveria ser -11 em vez de -10?

Carregando publicação patrocinada...
2

Os conteúdos no TabNews podem iniciar com 1 ou 0 TabCoin. Nesse caso, foi 1 - 12 + 1 = -10, sendo Valor inicial - Negativos + Positivos.

1

Valeu pela explicação, rafael. Acho que agora estou entendendo o motivo deste 1 ou 0 para pontuação inicial (estímulo) do conteúdo.

Fazendo uma busca no repositório do Tabnews, o arquivo pages/faq/index.public.js traz uma breve explicação como funciona esse estímulo inicial.

Como ganhar TabCoins?
As formas de ganho de TabCoins são:

 - **Criando um conteúdo:** existe um algoritmo que leva em consideração os TabCoins dos seus conteúdos mais recentes para definir quantos TabCoins você ganhará ao criar um novo conteúdo.
 - **Recebendo votos positivos:** quando outro usuário avalia positivamente seu conteúdo.
 - **Recompensa diária:** você pode ganhar TabCoins ao acessar o TabNews pelo menos uma vez no dia. Existe um algoritmo que leva em consideração as qualificações dos seus conteúdos mais recentes e também a quantidade de TabCoins que você possui. Quanto melhor avaliados forem seus conteúdos e menos TabCoins você possuir, mais receberá na recompensa diária.
2

Essa pergunta do FAQ é sobre TabCoins do usuário.

O TabCoin inicial do conteúdo tem a ver com a "relevância" dele, que hoje é uma verificação simples (veja o código aqui). Se você tentar criar um comentário ou publicação no site do TabNews com uma única palavra, por exemplo, receberá um aviso assim:

Tem certeza que deseja publicar essa mensagem curta? ⚠ Atenção: Pedimos encarecidamente que leia isso antes de fazer essa publicação.

Se escolher publicar, o conteúdo não terá o TabCoin inicial (começará em 0). O objetivo é desmotivar conteúdos muito rasos e que não precisariam ser publicados, como um comentário de agradecimento Valeu!.

Então, o TabCoin inicial é como um voto de confiança do TabNews no conteúdo publicado. No início do TabNews, essa verificação não existia, então todo conteúdo recebia o TabCoin inicial.

2

Valeu novamente, rafael, por indicar o código específico que faz essa criação de moedas.

Achei útil acompanhar esta postagem que estava sendo drasticamente negativada para entender como os Tabcoins/Tabcash são criados, debitados. No código fonte que indicou é possível entender o mecanismo. Infelizmente a postagem original desapareceu, contudo, pude ver em tempo algo correlacionado na Rede de Qualificações (últimas 300).

image
Timestamp: 20241014T145410Z

Estou quase certo de que o sistema do Tabnews mantém um rastreio de cada tipo de moeda criada e trocada entre pares, como se cada uma delas tivesse um número de série (UUID ou SN). Sabemos que parte dos Tabcoins foram criados como recompensa para os primeiros usuários que acreditaram na ideia da plataforma, compartilhando ideias, sugestões e alguns trabalhando pesado nos bastidores. Atualmente, um novo usuário entra na rede Tabnews com 0/0, ganhando parte com suas próprias publicações de valor e upvotes (distingue-se Tabcoins e Tabcash segundo a documentação). Se fosse permitido, eu faria um scrap para contabilizar toda moeda do ecossistema, pois da forma que estou entendendo, não há limites para criação de riqueza.

Para terminar, noto que a base de informações de tráfego de moeda (entre o gerador do Tabnews e usuários bem como entre usuários) é útil para fazer algumas análises, entender os mecanismos humanos por trás dessa rede de relacionamentos. Parabéns para quem teve a ideia de colocar a constelação de qualificações :).

3

Você pode obter os dados pela API, respeitando o rate limit, mas acho que "contabilizar toda moeda do sistema" é bastante coisa. Não sei uma forma mais adequada, mas você pode criar um issue no repositório. É melhor do que discutir aqui, porque as informações ficam mais fáceis de encontrar, permitindo que outros interessados vejam também.

Como estamos falando sobre análises, vou compartilhar uma que já fizeram aqui no TabNews: Leaderboard Tabnews: Reconhecendo a Excelência na Comunidade.

pois da forma que estou entendendo, não há limites para criação de riqueza.

Não há. Se o sistema ficar desequilibrado, isto é, muitos votos e muitos TabCoins sendo gerados, precisaremos realizar um ajuste manual para "dificultar" a geração. O Felipe Barso (aprendendofelipe) é quem mais trabalhou nesse código/algoritmo.

Parabéns para quem teve a ideia de colocar a constelação de qualificações :).

Também foi o Felipe Barso 👏

2

Grato pela dica, rafael. Devo abrir uma issue no repositório do Tabnews no Github assim que ele voltar ao ar (offline para mim aqui, mas tudo ok para eles). Com certeza será muito melhor finalizar a discussão por lá.

Agradeço por sua atenção, dedicando seu tempo na elaboração de cada resposta e indicação de outros links e experimentos realizados para ajudar sanar minhas dúvidas.

0
:: Área de rascunho :: Esta é uma postagem sobre postagem, não gerando Tabcoins propositalmente como definido nas regras do algoritmo do Tabnews. O conteúdo aqui produzido não tem valor informativo enquanto não finalizado. O espaço é utilizado apenas para criar e testar novas publicações, sua aparência, antes de serem publicadas definitivamente no portal.

Por favor, artistas, não pixar 🎨 🔫

0
:: RASCUNHO PARA DESENVOLVIMENTO :: favor, não pontuar, pois assim que publicado o conteúdo será removido

RASCUNHO - Arte em blocos de criptoativo

No começo de 2024, surgiu uma arte num bloco de um dos criptoativos mais conhecidos. A criação foi realizada pela MaraPool explorando algumas possibilidades já que detém seu próprio pool de mineração. Como as transações dentro do bloco podem ser rearranjadas conforme o minerador desejar, se o mesmo for consolidado será permanentemente registrado na blockchain. Agora, quando visualizadas numa matriz considerando o valor das taxas individuais, apresentam claramente um logotipo como mostra a imagem seguinte.

Detalhes

image
Fonte: mempool.space

Esta proeza está permanentemente registrada no bloco 836361


inclusão de arquivos dentro do bloco

Cada bloco comporta aproximadamente 4000 transações individuais de tamanho reduzido...

CenárioTamanho Médio de TransaçãoTamanho Máximo do BlocoMáximo de Transações por Bloco
Bloco tradicional (sem SegWit)250 bytes1MB (1.000.000 bytes)≈ 4.000 transações
Bloco otimizado com SegWit150 bytes4MB (4.000.000 bytes)≈ 26.666 transações
CampoTamanhoFinalidadeDescrição
Versão da Transação4 bytesIdentificação de versãoIndica o formato da transação
Contagem de EntradasVariávelNúmero de entradasDefine quantas entradas serão usadas na transação
Entrada 1Fonte de fundos
- Hash da Transação32 bytesHash da transação anteriorIdentifica a origem dos bitcoins
- Índice da Saída4 bytesÍndice da saída anteriorRefere-se a qual saída da transação anterior
- ScriptSigVariávelAssinatura digitalProva de que o remetente tem a chave para gastar
- Número de Sequência4 bytesAtualização de bloqueioPara operações que envolvem controle temporal
Contagem de SaídasVariávelNúmero de saídasDefine quantas saídas essa transação terá
Saída 1Destino dos fundos
- Valor8 bytesQuantidade de satoshisQuantidade de bitcoins a ser enviada
- ScriptPubKeyVariávelCondições para gastar fundosDefine as regras para gastar os bitcoins
Locktime4 bytesTempo de bloqueioData/bloco em que a transação pode ser confirmada

Cerca de um ano antes, o bloco 774628 teve a inclusão de uma imagem JPG (arquivo com , tornando-a uma data cujo marco está permanente dentro do maior bloco do bitcoin. A imagem original pode ser visualizada a seguir.

![image](https://ordinals.com/content/0301e0480b374b32851a9462db29dc19fe830a7f7d7a88b81612b9d42099c0aei0 =400x400)
Fonte: aqui

Para os leitores céticos fica a sugestão baixar a transação completa e fazer a extração dos cerca de 4 MB que compõem o arquivo JPEG.

Mais detalhes, vejas as matérias que veicularam na época

Qual deverá ser a próxima proeza?

0
RASCUNHO PARA DESENVOLVIMENTO (por favor, não pontuar, pois assim que publicado o conteúdo será removido)

Tendência e criptografia de última geração (State-of-the-Art Cryptography)

O estado da arte em criptografia enfatiza:

  • Eficiência: Algoritmos como AES, ChaCha20 e cifras leves para dispositivos IoT.
  • Segurança pós-quântica: proteção contra computação quântica com algoritmos como CRYSTALS e NTRUEncrypt.
  • Criptografia Homomórfica: Executar cálculos em dados criptografados sem descriptografá-los.
  • Provas de conhecimento zero: verificar uma declaração sem revelar os dados reais.
  • Criptografia Blockchain: Protegendo livros contábeis descentralizados com funções hash e algoritmos de curva elíptica.

Com curiosidade, é apresentada uma pequena lista expandida contendo as cifras históricas e modernas. Cobre desde as antigas técnicas de cifragem até os mais recentes algoritmos criptográficos já conhecidos. Estão agrupados para maior clareza. Se necessário, é fornecida alguma informação sobre algumas delas.

Detalhes
  1. Cifras antigas e clássicas
    Estas foram as primeiras técnicas de cifragem por processo manual, utilizadas por séculos antes do advento de máquinas para tal propósito:
  1. Cifras da era Medieval e Renascença
  • Vigenère
  • Autokey
  • Beaufort
  • Homophonic Substitution
  • Running Key
  • Bacon's (Cifra Estaganográfica)
  • Cardano Grille
  1. Cifras da era mecânica
    Empregadas a partir do século XIX até a WWII.
  • Enigma Machine M3 +
  • Lorenz
  • Jefferson Wheel (ou Bazeries Cylinder)
  • M-209 (Field Cipher Machine)
  • Purple (Japanese Cipher Machine)
  • SIGABA (American Cipher Machine)
  • Typex (British Cipher Machine)
  1. Cifra Estaganográfica e de Máscaras
    De acordo com o senso matemático, oculta a mensagem em vez criptografá-la.
  • Grille (mencionada acima)
  • Nicodemus
  • Book (quanto o texto encontra-se escondido dentro de um texto mais longo)
  • Pollux
  1. Criptografia clássica moderna
    Empregada de meados do século XX até o presente. Emprega algoritmos em vez de técnicas manuais.
  • Data Encryption Standard (DES)
  • Triple DES (3DES)
  • Advanced Encryption Standard (AES)
  • RSA (Rivest-Shamir-Adleman)
  • Diffie-Hellman Key Exchange
  • ElGamal
  • Blowfish
  • Twofish
  • Serpent
  • IDEA (International Data Encryption Algorithm)
  • RC4, RC5, RC6 (Rivest Ciphers)
  1. Stream Ciphers
    Criptografam os dados bit a bit.
  • RC4
  • A5/1 and A5/2 (empregada em redes móveis com tecnologia GSM)
  • Salsa20/ChaCha20
  • SEAL
  1. Block Ciphers (cifras de bloco)
    Criptografam blocos de dados com tamanho predefinido.
  • DES, AES (mentionado acima)
  • Blowfish, Twofish (mentionado acima)
  • CAST-128/CAST-256
  • Camellia
  • ARIA
  • Rijndael (precursor do algoritmo AES)
  1. Criptografia Post-Quântica
    Algoritmos projetados para resistir a ataques de computação quântica.
  • CRYSTALS (Cryptographic Suite for Algebraic Lattices)
    • CRYSTALS-Kyber (Key Encapsulation)
    • CRYSTALS-Dilithium (Digital Signatures)
  • NTRUEncrypt +
  • Picnic
  • FrodoKEM
  1. Hash Functions e Cryptographic Digests
    Essencialmente não são considerados cifras, mas essenciais em sistemas criptográficos para conferência de mensagens a partir de uma assinatura de tamanho reduzido.
  • MD5 (Message Digest 5)
  • SHA-1, SHA-2, SHA-3 (Secure Hash Algorithms)
  • Blake2
  • Argon2 (Key Derivation Function)
  • Outras
  1. Cifras híbricas e empregadas para fins específicos
    Usadas em combinação com outras técnicas criptográficas
  • Elliptic Curve Cryptography (ECC)
  • Galois/Counter Mode (GCM) for AES
  • Quantum Key Distribution (QKD)
  1. Cifras diversas e mais novas
    Raras, experimentais ou específicas para determinada situação (utilidade)
  1. Codificação para transmissão

Parte destas cifras são citadas no video "The Unbreakable Kryptos Code" relatando a decifragem de parte do enigma Kryptos.

0
:: RASCUNHO PARA DESENVOLVIMENTO :: favor, não pontuar, pois assim que publicado o conteúdo será removido

Compactaçao de imagem RGB para JPEG

JPEG (Joint Photographic Experts Group). O Processo eh realizado em 6 principais etapas:

  1. Transformação do espaço de cores RGB para Y'CbCr (Y' = luminance component; Cr, Cb = red and blue crominance components)

  2. Transformada discreta do cosseno (DCT) sobre os canais Y', Cb e Cr
    2.1 Imagem é dividida em blocos de 8 x 8 pixels
    2.2 Se a imagem não tem dimensões múltiplas de 8, deve ser preenchida a partir da lateral direita e parte inferior

  3. Quantização de acordo com a % referente à qualidade
    3.1 Canal Y' utiliza matriz de quantização Q_Y
    3.2 Canais Cb e Cr utilizam matriz de quantização Q_C

  4. Hufmann encoding para as quantidades AC. Quantidades DC utilizam compressão diferencial

  5. Compressão

  6. Escrita do arquivo JPEG

1) Transformação do espaço de cores

YCbCr definida pela CCIR 601-1 com Cb e Cr normalizados para o intervalo 0..CENTER em vez de -0.5 a 0.5. CENTER = 256 / 2 = 128.

O valores da transformação RGB para Y'CbCr foram calculados a partir da matriz inversa de Y'CbCr para RGB.

CJ =  128
Y  =  0,29900 * R + 0,58700 * G + 0,11400 * B
Cb = -0,16874 * R - 0,33126 * G + 0,50000 * B  + CENTERJSAMPLE
Cr =  0,50000 * R - 0,41869 * G - 0,08131 * B  + CENTERJSAMPLE

ou

| Y  |   |  0,299000   0,586998   0,114000 |   | R |           | 0,0 |
| Cb | = | -0,168736  -0,331263   0,500000 | x | G | + 128,0 * | 1,0 |
| Cr |   |  0,500000  -0,418686  -0,081313 |   | B |           | 1,0 |

Transformação inversa

| R |   |  1,00000  -0,000000   1,402000 |   | Y  |           | 1,0 |
| G | = |  1,00000  -0,344140  -0,714140 | x | Cb | - 128,0 * | 1,0 |
| B |   |  1,00000   1,772000   0,000000 |   | Cr |           | 1,0 |

Fonte: jccolor.c

2) Transformada discreta do cosseno (Discrete Cosine Transformation - DCT)

Como o próprio nome sugere, é uma transformação aplicada para valores discretos. Considerando os blocos com tamanho 8 x 8 pixel, são calculados 8 x 8 coeficientes da DCT.

Transformada direta

S[v][u] = (1/4) * C[u] * C[v] * Sum[x=0..7] Sum[y=0..7] s[y][x] \
                    * cos((2*x+1)*u*pi/16) * cos((2*y+1)*v*pi/16) 
int N = 8
// Função para calcular os coeficientes da DCT para um bloco 8x8
// Esta função apenas calcula os coeficientes não o bloco transformado
// Código não otimizado
void dct_basis(double dct_block[N][N], int u, int v) {
    // Optimization: it is a constant (u * PI) / (2 * N)
    for (int x = 0; x < N; x++) {
        for (int y = 0; y < N; y++) {
            double coeff_x = cos(((2.0 * x + 1.0) * u * PI) / (2.0 * N));
            double coeff_y = cos(((2.0 * y + 1.0) * v * PI) / (2.0 * N));
            dct_block[x][y] = coeff_x * coeff_y;
        }
    }
}

Transformada inversa

S[y][x] = (1/4) * Sum[u=0..7] Sum[v=0..7]  C[u] * C[v] * s[v][u] \
                     * cos((2*x+1)*u*pi/16) * cos((2*y+1)*v*pi/16) 

com:

C(u), C(v) = 1.0 / sqrt(2.0) para u, v = 0
C(u), C(v) = 1.0 para outros casos

As matrizes de transformação são ortogonais, logo, a transformada inversa se dá pela simples transposta da matriz de transformação. Expressando as equações na forma matricial:

Q = T x Y x T'
onde:
S = matriz com valores de amostra (Sample values of Y' or Cb or Cr)
T = matriz de transformação da DCT
Q = matriz de valores 
3) Matrizes de quantização

Os coeficientes de quantização para as componentes de luminância e crominância são apresentados em duas matrizes na referência indicada. Foram obtidos a partir de experimentos com limiares psicovisuais, derivados empiricamente usando luminância e crominância com subamostragem horizontal 2:1. Fornecem uma quantização com fator de qualidade de 50% (numa escala de 0 a 100%).

Os valores fornecidos na documentação são exemplos e não são necessariamente adequados para qualquer aplicação específica. Estes valores de quantização foram obtidos a partir da avaliação de resultados razoáveis em imagens de luminância e crominância de 8 bits por amostra. As características destas imagens podem ser conferidas na Figura 13 da referência.

Estes valores de quantização são apropriados para a normalização dos valores resultantes da DCT. Dividindo-os por 2, a imagem reconstruída resultante apresenta diferenças praticamente indistinguíveis da imagem original. Os valores resultantes devem ser arredondados para o inteiro mais próximo.

Matriz com coeficientes de quantização para frequências de luminância

16 11 10 16 124 140 151 161
12 12 14 19 126 158 160 155
14 13 16 24 140 157 169 156
14 17 22 29 151 187 180 162
18 22 37 56 168 109 103 177
24 35 55 64 181 104 113 192
49 64 78 87 103 121 120 101
72 92 95 98 112 100 103 199

Matriz com coeficientes de quantização para frequências de crominância

17 18 24 47 99 99 99 99
18 21 26 66 99 99 99 99
24 26 56 99 99 99 99 99
47 66 99 99 99 99 99 99
99 99 99 99 99 99 99 99
99 99 99 99 99 99 99 99
99 99 99 99 99 99 99 99
99 99 99 99 99 99 99 99

Fonte: itu-t81, pg. 143

Diferentes valores para o fator de qualidade modulam quão agressiva ou permissiva são essas matrizes:

JPEG permite ajustar o fator de qualidade (QF) entre 1 e 100:

  • QF = 100: Baixa compressão, alta qualidade.
  • QF = 50: Compressão nominal padrão.
  • QF < 50: Alta compressão, baixa qualidade.

Cada matriz de quantização é escalada conforme o algoritmo seguinte:

Q(u, v) = floor(Q_Y(u, v) * S / 100 + 0,5)

onde:
S = 5000 / QF      para (QF < 50)
S = 200 - 2 * QF   para (QF > 50)
3) Teoria
4) Exemplo numérico

As amostras 8 x 8 abaixo são dadas em formato PGM (Portable Gray Map) em modo texto. A porção da imagem é tomada de um artigo publicado em https://cgjennings.ca/articles/jpeg-compression (coordenadas rows = 88...95; cols = 48...55)

imagem

# Canal Red

P2
8 8
255
232 229 228 255 146  12  71  24 
228 239 235 254 191  17  40  47 
240 229 230 255 168  24  80  60 
242 244 235 255 145  17  21  48 
235 242 243 255 108   5   5 119 
238 238 240 255  83   0  51 130 
249 247 255 250  79  27  83 122 
249 255 225 131  82 103 128  91 


# Canal Green

P2
8 8
255
241 242 240 255 165  19  67  37 
243 242 238 255 218  32  41  50 
241 242 244 255 194  23  69  81 
244 243 245 255 170  82  83  26 
248 249 251 255 141  29  28 112 
248 244 247 255 130   0  51 130 
253 249 255 255 115  30  85 126 
252 255 226 146 103 114 137 109 


# Canal Blue

P2
8 8
255
254 251 248 255 162  20  64  39 
255 255 250 255 207  16  54  49 
253 253 253 255 186  18  90  79 
252 252 252 255 171  64  66  45 
255 255 255 255 131  20  19 121 
253 255 254 255 120   0  57 131 
255 252 255 255 104  21  71 103 
255 255 242 140  38  64  87  46 

Conversão dos canais RGB para YCbCr

# Canal Y (luminancia)

P2
8 8
255
240 239 237 255 159  17  68  33 
240 243 238 255 209  26  42  49 
242 239 241 255 185  23  75  74 
244 244 243 255 163  61  63  35 
245 248 249 255 130  21  20 115 
246 243 246 255 115   0  52 130 
252 249 255 254 103  28  83 122 
251 255 228 141  89 105 129  96 


# Canal Cb (Crominância azul)

P2
8 8
255
136 135 134 128 130 130 126 131 
137 135 135 128 127 123 135 128 
134 136 135 128 128 125 137 131 
132 132 133 128 133 130 130 134 
134 132 131 128 129 128 127 131 
132 135 133 128 131 128 131 129 
130 130 128 129 129 124 121 117 
130 128 136 128  99 105 105 100 


# Canal Cr (Crominância vermelho)

P2
8 8
255
122 121 121 128 119 124 130 121 
120 125 126 127 115 122 126 127 
127 121 120 128 116 129 132 118 
126 128 122 128 115  97  98 137 
121 124 124 128 112 117 117 131 
123 124 124 128 105 128 128 128 
126 127 128 125 111 127 128 128 
126 128 126 121 123 127 128 124 

Aplicando a transformada do cosseno para o canal Y obtém-se a matriz T

H = [
   0.353553   0.353553   0.353553   0.353553   0.353553   0.353553   0.353553   0.353553
   0.490393   0.415735   0.277785   0.097545  -0.097545  -0.277785  -0.415735  -0.490393
   0.461940   0.191342  -0.191342  -0.461940  -0.461940  -0.191342   0.191342   0.461940
   0.415735  -0.097545  -0.490393  -0.277785   0.277785   0.490393   0.097545  -0.415735
   0.353553  -0.353553  -0.353553   0.353553   0.353553  -0.353553  -0.353553   0.353553
   0.277785  -0.490393   0.097545   0.415735  -0.415735  -0.097545   0.490393  -0.277785
   0.191342  -0.461940   0.461940  -0.191342  -0.191342   0.461940  -0.461940   0.191342
   0.097545  -0.277785   0.415735  -0.490393   0.490393  -0.415735   0.277785  -0.097545
]

T = H' x Y x H = [
  1332    241    -29   -134    234     87     20     70 
  -344    -76    -93    107    -55    -12    -65     11 
   270     41     66    -41     23     25      3     20 
  -105     27    -62    -27     40    -12      4    -17 
   137     20     39     28    -35     10     14      4 
     1      7    -39     -5     -5     38    -10     -6 
    71      6     32     -1    -10     19     -9     11 
    37     15      6    -34     21      9      3     -1 
]
Nota: cálculo dos coeficiente da matriz H
#include<stdio.h>
#include<math.h>

double H(double n, double u, double x) {
  return sqrt(((u==0.0)?1.0:2.0)/n)*cos( (2.0*x+1.0)*u*M_PI/(2.0*n) );
}

int main(int argc, char *argv[], char *env[]) {
  double n = 8.0;
  for(double u = 0; u<n; u++) {
    for(double x = 0; x<n; x++) printf("%11.6f", H(n, u, x));
    printf("\n");
  }
  return 0;
}

Matriz de quantização para a luminância (Y), fator de qualidade 50 (de 0 a 100):

Qy_50 = [
    16    12    14    14    18    24    49    72
    11    12    13    17    22    35    64    92
    10    14    16    22    37    55    78    95
    16    19    24    29    56    64    87    98
    24    26    40    51    68    81   103   112
    40    58    57    87   109   104   121   100
    51    60    69    80   103   113   120   103
    61    55    56    62    77    92   101    99
]

A matriz resultante é a divisão de cada elemento da matriz T pelo elemento correspondente na matriz de quantização Qy_50

T_Qy50 = [
    83     20     -2    -10     13      4      0      1 
   -31     -6     -7      6     -2      0     -1      0 
    27      3      4     -2      1      0      0      0 
    -7      1     -3     -1      1      0      0      0 
     6      1      1      1     -1      0      0      0 
     0      0     -1      0      0      0      0      0 
     1      0      0      0      0      0      0      0 
     1      0      0     -1      0      0      0      0 
]

Aplica-se o algoritmo de captura em zig-zag

   20,-31,27,-6,-2,-10,-7,3,-7,6,1,4,6,13,4,-2,-2,-3,1,0,...,0

Prossegue com o algoritmo de Huffman para posteriormente compactar os coeficientes AC. O primeiro coeficiente em (1,1) = 83 refere-se à componente DC (contínua) e é excluído desta compactação sendo combinado com os demais de outras matrizes e codificado diferencialmente.

5) Source code
6) References

ToDo:

  • Equações de transformação de espaços de cores
  • Matrizes de quantização para luminância Y' e crominâncias Cb e Cr
  • Como alterar o fator de qualidade
  • Teoria
  • Exemplo numérico
  • Transcrever source code to javascript
  • Incluir references
  • Corrigir a ortografia e pontuação
  • Particularidades (precisão, inteiros, algoritmos etc.)
0
:: RASCUNHO PARA DESENVOLVIMENTO :: favor, não pontuar, pois assim que publicado o conteúdo será removido

O que são as constantes mágicas encontradas no algoritmo SHA-256?

SHA-256 é uma das funções hash que faz parte da família SHA-2 (sucessora da família SHA-1) definidas no U.S. National Institute of Standards and Technology - Federal Information Processing Standards Publication (FIPS PUB) 180-4 update 1 publicado em agosto de 2015 (sob revisão após receber sugestões) e previamente definido nos padrões anteriores FIPS PUB 180, FIPS PUB 180-1, FIPS PUB 180-2, 180-2 update 1, FIPS PUB 180-3, FIPS PUB 180-4. Outras funções da mesma família são: SHA-224, SHA-256, SHA-384, SHA-512, SHA-512/224, SHA-512/256, sendo o valor numérico o número de bits resultante do resumo ou digest.

Existem diferentes implementações (1, 2, 3) do algoritmo SHA-256, contendo 72 constantes hardcoded para eficiência e padronização. Tais constantes desempenham um papel crucial em determinadas funções internas, sendo 8 delas, denominadas H_j, participantes na etapa de inicialização dos valores de hash e outras 64 constantes, denominadas K_i, participantes na etapa de compressão.

Detalhes
---------------------------------- K ----------------------------------   --- H ---
428A2F98 71374491 B5C0FBCF E9B5DBA5 3956C25B 59F111F1 923F82A4 AB1C5ED5    6A09E667
D807AA98 12835B01 243185BE 550C7DC3 72BE5D74 80DEB1FE 9BDC06A7 C19BF174    BB67AE85
E49B69C1 EFBE4786 0FC19DC6 240CA1CC 2DE92C6F 4A7484AA 5CB0A9DC 76F988DA    3C6EF372
983E5152 A831C66D B00327C8 BF597FC7 C6E00BF3 D5A79147 06CA6351 14292967    A54FF53A
27B70A85 2E1B2138 4D2C6DFC 53380D13 650A7354 766A0ABB 81C2C92E 92722C85    510E527F
A2BFE8A1 A81A664B C24B8B70 C76C51A3 D192E819 D6990624 F40E3585 106AA070    9B05688C
19A4C116 1E376C08 2748774C 34B0BCB5 391C0CB3 4ED8AA4A 5B9CCA4F 682E6FF3    1F83D9AB
748F82EE 78A5636F 84C87814 8CC70208 90BEFFFA A4506CEB BEF9A3F7 C67178F2    5BE0CD19
Código elaborado para cálculo das 72 constantes
echo "" | awk --sandbox '{
    j = 0;  # Inicializacao do indice para constantes H
    
    # Numeros primos de 2 a 317
    primes = "  2,   3,   5,   7,  11,  13,  17,  19,  23,  29,  31,  37,  41,"\
             " 43,  47,  53,  59,  61,  67,  71,  73,  79,  83,  89,  97, 101,"\
             "103, 107, 109, 113, 127, 131, 137, 139, 149, 151, 157, 163, 167,"\
             "173, 179, 181, 191, 193, 197, 199, 211, 223, 227, 229, 233, 239,"\
             "241, 251, 257, 263, 269, 271, 277, 281, 283, 293, 307, 311, 313 ";
    
    n = split(primes, p, ",");  # Transcreve para vetor os números primos dados
    # Imprime um cabecalho
    printf("---------------------------------- K ");
    printf("----------------------------------   --- H ---\n");
    
    for(i = 1; i = 64; i++) {
        # Calcula e imprime as constantes K( 1) até K(64)
        c = p[i]^(1/3); k = int(2^32*(c-int(c))); printf("%08X ", k);
        if(!(i%8)) {
            j++; 
            # Calcula e imprime as constantes H(1) até H(8)
            b = p[j]^(1/2); h = int(2^32*(b - int(b))); printf("   %08X\n", h);
         };
    }
}'

Mas, qual é a origem, o significado e o motivo destas constantes?

Ao utilizar as partes fracionárias das raízes cúbicas dos 64 primeiros números primos (NIST.FIPS.180-4, pag. 11) para geração das constantes K e utilizar as partes fracionárias das raízes quadradas dos 8 primeiros números primos (NIST.FIPS.180-4, pag. 15) para geração das constantes H, cria-se, desta forma, um conjunto de constantes que tornam a função hash resistente a ataques, garantindo um comportamento complexo e menos previsível. Para obter as constantes, aquelas partes fracionárias são então multiplicadas por 2^32, os resultados truncados para inteiros e então impressos na base numérica hexadecimal. Tais valores são então facilmente obtidos de maneira determinística e, para que haja consistência das saídas de hash em diferentes implementações do algoritmo, tais valores devem ser mantidos fixos. Essas constantes mágicas usadas no algoritmo de hash SHA-256 proporcionam uma não-linearidade para a função hash.

Aplicações do SHA-256

SHA-256 é amplamente utilizada como função criptográfica de hash, produzindo uma saída de 256 bits independente do número de bytes fornecidos na sua entrada (um simples caractere ou arquivos inteiros). Outra aplicação relevante é no algoritmo de mineração de um dos ativos digitais mais conhecidos, onde se aplica a função duas vezes, ou seja, sha256(sha256(conteúdo)) e por isso às vezes é denominada sha256d.

Por que sha256(sha256(conteúdo))?

O Bitcoin encadeia o algoritmo de hash SHA-256 duas vezes no processo de criação de um hash para um determinado bloco, especificamente ao cabeçalho do bloco. O cabeçalho do bloco inclui dados importantes como o hash do bloco anterior, a estampa de hora (timestamp), o nonce (um número usado uma vez) entre outros elementos.

Estrutura de um cabeçalho

image

O duplo hash resultante é uma representação compacta do estado de todo o bloco e é usado no mecanismo de prova de trabalho (proof of work), onde os mineradores competem para encontrar um hash que seja inferior a um determinado limite alvo denominado difficult.

O duplo hash serve a vários propósitos:

  • Segurança aprimorada: Ao fazer hash dos dados duas vezes, o Bitcoin adiciona uma camada adicional de segurança. Embora o SHA-256 já seja considerado seguro, o hash duplo torna ainda mais difícil para os "invasores" encontrarem colisões (dois dados diferentes que produzem o mesmo hash) ou pré-imagens (encontrar uma entrada que faz hash para uma saída específica).

  • Saída Determinística: O uso de SHA-256 duplo garante que a saída seja determinística, o que significa que a mesma entrada sempre produzirá a mesma saída. Ao aplicar a mesma função hash duas vezes, quaisquer pequenas alterações na entrada levarão a saídas hash significativamente diferentes.

  • Resistência a certos ataques: o hash duplo pode mitigar certos tipos de ataques, especificamente aqueles que visam a primeira camada do processo de hash. Se um invasor puder interferir (influenciar) a entrada do primeiro hash, deverá também precisará lidar com o segundo hash, tornando-o mais complexo e demorado.

  • Consistência do comprimento de saída: Hashing duas vezes garante um comprimento de saída consistente, o que é crucial para funções criptográficas. Mesmo que a primeira função hash tivesse características diferentes, a segunda camada impõe um comprimento e estrutura de saída uniformes.

Funções hash são construídas de maneira que teoricamente não seja possível reverter o processo a partir das saídas, ou seja, recriar uma entrada (um arquivo) a partir de seu hash. Entretanto, hash de mensagens curtas ou mesmo arquivos estruturados, podem ser revertidos a partir de ataques via força bruta como rainbow tables.


Fontes consultadas...

http://csrc.nist.gov/publications/fips/fips180-3/fips180-3_final.pdf
https://csrc.nist.gov/publications/fips#fips180-4
https://datatracker.ietf.org/doc/html/rfc6234
https://eprint.iacr.org/2011/565.pdf

http://www.hashcash.org/papers/hashcash.pdf
https://bitcoin.org/bitcoin.pdf
https://armantheparman.com/sha256
https://armantheparman.com/dicev1

0
:: RASCUNHO PARA DESENVOLVIMENTO :: favor, não pontuar, pois assim que publicado o conteúdo será removido

Rascunho - O que são Merkle trees?

merkle_blk75000.py

Detalhes
# Uses      :  python 2
# Dependency:  hashlib
import hashlib

# Hash pairs of items recursively until a single value is obtained
def merkle(hashList):
    if len(hashList) == 1:
        return hashList[0]
    newHashList = []
    # Process pairs. For odd length, the last is skipped
    for i in range(0, len(hashList)-1, 2):
        newHashList.append(hash2(hashList[i], hashList[i+1]))
    if len(hashList) % 2 == 1: # odd, hash last item twice
        newHashList.append(hash2(hashList[-1], hashList[-1]))
    return merkle(newHashList)

def hash2(a, b):
    # Reverse inputs before and after hashing
    # due to big-endian / little-endian nonsense
    a1 = a.decode('hex')[::-1]
    b1 = b.decode('hex')[::-1]
    h = hashlib.sha256(hashlib.sha256(a1+b1).digest()).digest()
    return h[::-1].encode('hex')

# https://blockexplorer.com/rawblock/0000000000000000e067a478024addfecdc93628978aa52d91fabd4292982a50  (outdated)
# wget -qO- https://mempool.space/api/block/00000000000ace2adaabf1baf9dc0ec54434db11e9fd63c1819d8d77df40afda/txids
# expected Merkle Root
# wget -qO- https://mempool.space/api/block/75000
# ed385c2dbc69aa24965909c7d9d11bbd99faa085cb4ec17865d9b557ffb3a68a
#
txHashes = ["5277cf3790381c2cc2b071038d8c35b3b601207c92f8aec15978a5f01ecf8319",
"182c2ed191a35ea496ce84c42d8beee6f9d82b9f063de2e45a54692bb043696a",
"707e86e5e2356cb53a2edf0be391d56cfc998bcfa05a13a5772ef474c5eba105",
"711e15a9a819de4d1269d71de9744dedf9b6c32bba36bb0196f003f6507d4bb4",
"8c1e409484e30c205698647753cca07d826c34756773bd0432202487f28e2d54",
"abfaf8e7ad6241ca5161e517baade1275cf6333d0d118d221f894813bacb4f78"]

print merkle(txHashes)

Fontes

0
:: RASCUNHO PARA DESENVOLVIMENTO :: favor, não pontuar, pois assim que publicado o conteúdo será removido

Rotinas para operações com matrizes em C. Portável para Javascript
Por que não utilizar LAPACK?

Code in C
#include <stdio.h>
#include <math.h>

// Prototypes
void mxinverse(double* matrix, int n);
void mxmult(double* matrixA, double* matrixB, double* matrixC,
            int mA, int nA, int mB, int nB);
void mxadd(double* matrixA, double* matrixB, double* matrixC,
            int mA, int nA, int mB, int nB, double alpha, double beta);


// ToDo: Improve this function returning a status value
void mxinverse(double* matrix, int n) {
    int i, j, k;
    double sum;

    for (i = 0; i < n; i++) {
        for (j = i; j < n; j++) {
            sum = matrix[i * n + j];
            for (k = i - 1; k >= 0; k--) {
                sum -= matrix[i * n + k] * matrix[j * n + k];
            }
            if (i == j) {
                // What happen when sum < 0.0?
                matrix[i * n + i] = sqrt(sum);
            } else {
                // What happen when matrix[i * n + i] == 0.0?
                // ToDo: return a status value
                matrix[j * n + i] = sum / matrix[i * n + i];
            }
        }
    }

    for (i = 0; i < n; i++) {
        for (j = i; j < n; j++) {
            sum = (i == j) ? 1.0 : 0.0;
            for (k = j - 1; k >= i; k--) {
                sum -= matrix[j * n + k] * matrix[j * n + k];
            }
            // What happen when matrix[i * n + i] == 0.0?
            // ToDo: return a status value
            matrix[j * n + i] = matrix[j * n + i] / matrix[i * n + i];
            matrix[i * n + j] = sum / matrix[i * n + i];
        }
    }

    for (i = 0; i < n; i++) {
        for (j = i + 1; j < n; j++) {
            for (k = i + 1; k < j; k++) {
                matrix[j * n + i] -= matrix[j * n + k] * matrix[k * n + i];
            }
                // What happen when matrix[i * n + i] == 0.0?
                // ToDo: return a status value
                matrix[j * n + i] /= matrix[j * n + j];
        }
    }
}


// C[i,j] = alpha * ( A[i,j] * B[i,j] ) + beta * C[i,j] // C = A  * B
// C[i,j] = alpha * ( A[j,i] * B[i,j] ) + beta * C[i,j] // C = A' * B
// C[i,j] = alpha * ( A[j,i] * B[j,i] ) + beta * C[i,j] // C = A' * B'
// C[i,j] = alpha * ( A[i,j] * B[j,i] ) + beta * C[i,j] // C = A  * B'
// 
void mxmult(double* matrixA, double* matrixB, double* matrixC,
            int mA, int nA, int mB, int nB, double alpha, double beta) {               
  // ToDo: Implement the algorithm
}


// C[i,j] = alpha * A[i,j] + beta * B[i,j] + gamma
//
// Changing alpha and beta, it is possible to implement mxsub
void mxadd(double* matrixA, double* matrixB,
           int mA, int nA, int mB, int nB,
           double alpha, double beta, double gamma) {
    
}


_

0
:: RASCUNHO PARA DESENVOLVIMENTO :: favor, não pontuar, pois assim que publicado o conteúdo será removido

É possível incluir SVG inline em postagens no Tabnews? O formato vetorial para gráficos é mais eficiente e faz parte do markdown, independente de um link para imagens externas. Imagens complexas, como fotos, ainda precisam do armazanamento em formato raster.

<svg
  xmlns="http://www.w3.org/2000/svg"
  width="142px"
  height="23px"
  fill="none"
>
<foreignObject width="142px" height="23px">
<div xmlns="http://www.w3.org/1999/xhtml">
<style>
.pill{
    display: flex;
    background-color: transparent;
    width: max-content;
    font-family: 'Open Sans', sans-serif;
    border-radius: 4px;
}
.pillLabel{
    display: flex;
    width: max-content;
    padding: 4px;
    padding-left: 8px;
    padding-right: 8px;
    border-top-left-radius: 4px;
    border-bottom-left-radius: 4px;
    font-size: 12px;
    color: rgb(254 215 170);
    background-color: rgb(136 19 55);
}
.pillIcon{
  margin-right: 4px;
  width: 14px;
  height: 14px;
}
.pillCount{
    color: rgb(136 19 55);
    background-color: rgb(254 215 170);
    width: max-content;
    border-top-right-radius: 4px;
    border-bottom-right-radius: 4px;
    padding: 4px;
    padding-left: 8px;
    padding-right: 8px;
    letter-spacing: 1px;
    font-size: 12px;
}

@keyframes heartbeat {
  0% {
      transform: scale(1);
  }
  25% {
      transform: scale(1.1);
  }
  40% {
      transform: scale(1);
  }
  60% {
      transform: scale(1.1);
  }
  100% {
      transform: scale(1);
  }
}

.heartbeat {
  display: inline-block;
  animation: heartbeat 1.5s infinite;
  transform-origin: center;
  image-rendering: -webkit-optimize-contrast;
  image-rendering: crisp-edges;
  backface-visibility: hidden;
  will-change: transform;
}

</style>
<div class="pill">
<span class="pillLabel">
<svg xmlns="http://www.w3.org/2000/svg" class="pillIcon heartbeat" fill="none" viewBox="0 0 24 24" stroke="currentColor">
  <path name="bar" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 19v-6a2 2 0 00-2-2H5a2 2 0 00-2 2v6a2 2 0 002 2h2a2 2 0 002-2zm0 0V9a2 2 0 012-2h2a2 2 0 012 2v10m-6 0a2 2 0 002 2h2a2 2 0 002-2m0 0V5a2 2 0 012-2h2a2 2 0 012 2v14a2 2 0 01-2 2h-2a2 2 0 01-2-2z" />
</svg>
Profile Views</span>
<span class="pillCount" > 42 </span>
</div>
</div>
</foreignObject>
</svg>
0
:: RASCUNHO PARA DESENVOLVIMENTO :: favor, não pontuar, pois assim que publicado o conteúdo será removido

RASCUNHO - É possível se livrar dos webcrawlers?


Conteúdo para ser publicado em breve.

Diferentes publicações apresentam procedimento de como baixar o conteúdo estático de um website por completo, usando recursos disponíveis na linha de comando Linux como wget, curl entre outras possíveis opções programadas em Python, Perl etc.

Detalhes
user_agent="Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/129.0.0.0 Safari/537.36"

wget --verbose --mirror --no-parent --continue --page-requisites \
     --adjust-extension --convert-links --no-clobber --timestamping \
     --server-response --limit-rate=10k --wait=10 --random-wait \
     --no-cache --user-agent="${user_agent}" --no-check-certificate <website.address>

Mas existe alguma maneira de se defender dessa prática quando a mesma se torna nociva para o servidor, aumentando a carga para um propósito realizado por não-humanos? Contratar um proxy que implemente desafios (CAPTCHA) pode ser uma solução.

Mas será que é possível criar uma solução independente de proxy? E se a página web fosse dinâmica, ou seja, montada em tempo de carga usando somente javascript e uma conexão via websocket seguro com o servidor (nos códigos seguintes é ws em vez de wss)? Por meio do websocket o Javascript obtém o conteúdo a ser montado na página no lado do cliente. Tais recursos dinâmicos ainda não são interpretados pelos crawlers burros.


Esta ideia é possível e o fluxo básico para realizar isso envolve os seguintes passos:

1. Conexão WebSocket com o Servidor

A primeira etapa é estabelecer uma conexão WebSocket com o servidor. O WebSocket permite uma comunicação bidirecional em tempo real, ideal para atualizar e carregar dados dinâmicos.

const socket = new WebSocket('ws://servidor.com:porta');

// Quando a conexão é aberta
socket.onopen = function(event) {
    console.log("Conectado ao servidor via WebSocket.");
    socket.send("Solicitando dados para a página");
};

// Quando uma mensagem é recebida do servidor
socket.onmessage = function(event) {
    const data = JSON.parse(event.data);
    montarPagina(data);
};

// Tratamento de erros
socket.onerror = function(error) {
    console.log("Erro na conexão WebSocket:", error);
};

// Quando a conexão é fechada
socket.onclose = function(event) {
    console.log("Conexão WebSocket fechada.");
};

2. Recebendo o Conteúdo

Quando o servidor envia os dados, eles podem estar no formato JSON (ou outro formato estruturado). Ao receber os dados, o JavaScript no lado do cliente pode processar e montar o conteúdo da página dinamicamente.

3. Construção da Página no Lado do Cliente

Uma vez que os dados são recebidos, você pode manipulá-los e gerar o conteúdo da página dinamicamente usando DOM (Document Object Model) ou técnicas como innerHTML.

Exemplo simples de código:

function montarPagina(data) {
    const body = document.body;

    // Criar elementos de acordo com os dados recebidos
    const titulo = document.createElement('h1');
    titulo.textContent = data.titulo;

    const conteudo = document.createElement('p');
    conteudo.textContent = data.conteudo;

    // Adicionar os elementos na página
    body.appendChild(titulo);
    body.appendChild(conteudo);
}

4. Servidor WebSocket

Do lado do servidor, você precisa configurar um serviço WebSocket que envie os dados requisitados ao cliente. O servidor deve manter a conexão aberta enquanto for necessário para enviar novos dados dinamicamente ou quando solicitado.

Um exemplo básico de servidor WebSocket em Node.js:

const WebSocket = require('ws');
const wss = new WebSocket.Server({ port: 8080 });

wss.on('connection', (ws) => {
    console.log('Cliente conectado');

    ws.on('message', (message) => {
        console.log('Mensagem recebida: %s', message);
        const dadosPagina = {
            titulo: "Bem-vindo à minha página!",
            conteudo: "Este conteúdo foi carregado dinamicamente via WebSocket."
        };
        ws.send(JSON.stringify(dadosPagina));
    });

    ws.on('close', () => {
        console.log('Cliente desconectado');
    });
});

Benefícios:

  • Atualização em tempo real: O WebSocket permite que o servidor envie atualizações em tempo real ao cliente sem a necessidade de recarregar a página.
  • Eficiência: Reduz a sobrecarga de requisições HTTP/HTTPS repetidas, já que a conexão WebSocket permanece aberta.
  • Experiência do usuário: O conteúdo pode ser carregado e atualizado dinamicamente conforme necessário.

Desafios:

  • Gestão de estados e reconexão: É necessário garantir que o cliente possa lidar com a desconexão e reconectar caso a comunicação falhe.
  • Segurança: A comunicação via WebSocket deve ser protegida para evitar ataques como Man-in-the-Middle (usando WSS em vez de WS).

Essa abordagem é útil para aplicações em tempo real ou dinâmicas, como sistemas de votação, chat ou dashboards de monitoramento em tempo real. Por ser um conteúdo dinâmico, os crawlers burros não conseguirão baixar o conteúdo, mas apenas a página principal contendo o mínimo, básico para que o navegador (Chrome, Firefox, Opera etc.) consiga iniciar a carga e montagem da página dinamicamente.

[Keywords: crawler, defeat, dynamic page, javascript, websocket] // for [index|filter]ing purposes

0
:: RASCUNHO PARA DESENVOLVIMENTO :: favor, não pontuar, pois assim que publicado o conteúdo será removido

RASCUNHO: WhatsApp Web com nova interface

Na última quarta-feira (), ao abrir o WhatsApp Web, notei uma nova janela de pareamento. Será uma novidade ou um ataque man in middle?

image

Caso alguém também notou essa nova janela e possa compartilhar a experiência, enriquecerá esse achado.